I recently wrote a shader for a terrain. When that worked, i wanted to move on to lighting, so i calculated normals, drew them to make sure they were ok, and proceeded to follow the lighthouse3d tutorial on per-pixel lighting (http://www.lighthouse3d.com/opengl/glsl/index.php?ogldir1). This was the resulting shader:
Vertex:
// Send the height and texture coordinates //
height = gl_Vertex.y;
gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;
// Calculate the eye-space normal //
normal = normalize(gl_NormalMatrix * gl_Normal);
// Calculate the direction of the light //
lightDir = normalize(vec3( gl_LightSource[0].position));
// Compute the diffuse and ambient terms //
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;
// Set the position of the current vertex //
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
Fragment:
// Compute lighting //
vec3 n;
float NdotL;
// The ambient term will always be present //
vec4 lightColor = ambient;
// Normalize the normal of the pixel //
n = normalize(normal);
// Compute the dot product between normal and ldir //
NdotL = max(dot(n,lightDir),0.0f);
// If the angle is not 0, the diffuse term must be calculated //
if (NdotL > 0.0f)
{
lightColor += diffuse * NdotL;
}
gl_FragColor = lightColor;
that didnt work. The intensity of the light changed when i moved the camera, which is just wrong. Then i realized i had been setting my light position before my modelview transforms, so then i did this:
main.cpp
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Cam.Look(); // Transforms happened here //
GLfloat position[] = { 1.0f, 0.0f, 0.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, position);
//DrawGrid(&verts[0], 257, waterShader);
DrawTerrain(&testTerrain);
that didnt work either. Same sort of problem, light intensity change based on the cameras distance. So then i tried putting the glLightfv call BEFORE the modelview transform, and got rid of the gl_NormalMatrix call in my vertex shader:
vertex:
...
// Calculate the eye-space normal //
normal = normalize(gl_Normal);
// Calculate the direction of the light //
lightDir = normalize(vec3( gl_LightSource[0].position));
...
That worked perfectly.
My question is simply why? It seems rather odd and if i dont understand it now it will come back to haunt me.
Thanks