So, it helps to transform everything to eye space before doing lighting calculations? I’m having trouble with the transforming part. I’ve got the normals transformed right, but when I apply translations (when the object is not in the center of the world coordinate system), the lighting remains exactly the same.
I have confirmed that there are no problems with any C++ code.
I will paste my shaders…
QUESTION: I would like to know what I’m not transforming right, and how I’m supposed to transform it.
vertex shader…
const int MAXLIGHTS = 4;
uniform int lightcount;
uniform vec4 lPositions[MAXLIGHTS];
//V = transformed vertex
//N = transformed normal
//E = eye vector
//L = vector from vertex to light
varying vec3 V, N, E, L[MAXLIGHTS];
void main()
{
int lcount = lightcount > MAXLIGHTS ? MAXLIGHTS : lightcount;
V = vec3(gl_ModelViewMatrix * gl_Vertex);
N = gl_NormalMatrix * gl_Normal;
E = normalize(-V);
for(int i = 0; i < lcount; i++)
{
L[i] = gl_NormalMatrix * normalize(vec3(lPositions[i] - gl_Vertex));
}
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}
fragment shader…
const int MAXLIGHTS = 4;
uniform int lightcount;
uniform vec4 lDiffuses[MAXLIGHTS];
uniform vec4 lAmbients[MAXLIGHTS];
varying vec3 V, N, E, L[MAXLIGHTS];
uniform bool justcolor;
void main()
{
if(justcolor)
{
gl_FragColor = gl_Color;
return;
}
int lcount = lightcount > MAXLIGHTS ? MAXLIGHTS : lightcount;
vec4 ambient;
vec4 diffuse;
vec4 specular = vec4(0.0, 0.0, 0.0, 0.0);
vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
vec3 H;
float NL;
float NH;
for(int i = 0; i < lcount; i++)
{
specular = vec4(0.0, 0.0, 0.0, 0.0);
ambient = lAmbients[i];
NL = dot(N, L[i]);
diffuse = lDiffuses[i] * max(NL, 0.0);
if(NL > 0.0)
{
H = normalize(E + L[i]);
NH = max(0.0, dot(N, H));
specular = pow(NH, 40.0) * vec4(0.3, 0.3, 0.3, 1.0);
}
color += gl_Color * (diffuse + ambient) + specular;
}
gl_FragColor = color;
}
This code only makes sense if
lPositionsis in model space. And that’s highly unlikely.The general way this works is that you pass light positions in eye space, so there’s no need to transform them.
Also, L and E are entirely superfluous. You will get more accurate results by computing these in the fragment shader. The computations are quite simple and cheap, and since you need to renormalize them (which you don’t do) in the fragment shader anyway, you’re not really getting anything.
L is just the eye-space light position – the eye-space surface position. E is just the direction from the eye to the position, which is the normalized negation of the eye-space surface position.