OpenGL Shading Language Tutorials

Per Fragment Lighting


In OpenGL Shading language you can access built in OpenGL lighting states. Implementing an advanced lightning model would be compatible with standard OpenGL statements.
Update:
This works with ATI Catalyst 4.1 (and higher) drivers only.


Accessing Lighting States:

You can access all OpenGL Lighting states and some derived states. The following tables can also be found in the OpenGL Shading Language specification:

Light Source Paramters:
You can access light source parameters defined in your OpenGL Program with the pre-defined uniform variable "gl_LightSource". In the C++ application you simply define values with "glLight*".

struct gl_LightSourceParameters {
 vec4 ambient;              // Acli
 vec4 diffuse;              // Dcli
 vec4 specular;             // Scli
 vec4 position;             // Ppli
 vec4 halfVector;           // Derived: Hi
 vec3 spotDirection;        // Sdli
 float spotExponent;        // Srli
 float spotCutoff;          // Crli
                            // (range: [0.0,90.0], 180.0)
 float spotCosCutoff;       // Derived: cos(Crli)
                            // (range: [1.0,0.0],-1.0)
 float constantAttenuation; // K0
 float linearAttenuation;   // K1
 float quadraticAttenuation;// K2
};

uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
 

Material Parameters:
You can access the values you set in C++ with "glMaterial*" with gl_FrontMaterial and gl_BackMaterial.

struct gl_MaterialParameters
{
 vec4 emission;    // Ecm
 vec4 ambient;     // Acm
 vec4 diffuse;     // Dcm
 vec4 specular;    // Scm
 float shininess;  // Srm
};
uniform gl_MaterialParameters gl_FrontMaterial;
uniform gl_MaterialParameters gl_BackMaterial;


Derived state from products of light and material:

struct gl_LightModelProducts
{
  vec4 sceneColor; // Derived. Ecm + Acm * Acs
};
uniform gl_LightModelProducts gl_FrontLightModelProduct;
uniform gl_LightModelProducts gl_BackLightModelProduct;


struct gl_LightProducts {
 vec4 ambient;    // Acm * Acli 
 vec4 diffuse;    // Dcm * Dcli
 vec4 specular;   // Scm * Scli
};
uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
 

Shader Source Code

Vertex Shader

varying vec3 N;
varying vec3 v;
void main(void)
{
   v = vec3(gl_ModelViewMatrix * gl_Vertex);

   N = normalize(gl_NormalMatrix * gl_Normal);
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


Fragment Shader

varying vec3 N;
varying vec3 v;
void main (void)
{
vec3 L = normalize(gl_LightSource[0].position.xyz - v); 
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N)); 

//calculate Ambient Term: vec4 Iamb = gl_FrontLightProduct[0].ambient; //calculate Diffuse Term: vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0); // calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[0].specular * pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
// write Total Color:
gl_FragColor = gl_FrontLightModelProduct.SceneColor + Iamb + Idiff + Ispec; 

}

Questions:

1. Implement lighting for n lights, where n = gl_MaxLights. (note: there is no good solution for this question with current drivers yet)
2. This implementation uses point lights only. Add spot light support.

Possible solution with 2 lights:


Author: Martin Christen, christen@clockworkcoders.com

 

 

© 2003-2004 by Martin Christen. All Rights Reserved.
christen@clockworkcoders.com