Grimfate202

02-05-2011, 10:57 AM

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 :D

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 :D