1

I've been trying to make a basic static point light using shaders for an LWJGL game, but it appears as if the light is moving as the camera's position is being translated and rotated. These shaders are slightly modified from the OpenGL 4.3 guide, so I'm not sure why they aren't working as intended. Can anyone explain why these shaders aren't working as intended and what I can do to get them to work?

Vertex Shader:

varying vec3 color, normal;
varying vec4 vertexPos;

void main() {
    color = vec3(0.4);
    normal = normalize(gl_NormalMatrix * gl_Normal);
    vertexPos = gl_ModelViewMatrix * gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragment Shader:

varying vec3 color, normal;
varying vec4 vertexPos;

void main() {
    vec3 lightPos = vec3(4.0);
    vec3 lightColor = vec3(0.75);
    vec3 lightDir = lightPos - vertexPos.xyz;
    float lightDist = length(lightDir);
    float attenuation = 1.0 / (3.0 + 0.007 * lightDist +  0.000008 * lightDist * lightDist);
    float diffuse = max(0.0, dot(normal, lightDir));
    vec3 ambient = vec3(0.4, 0.4, 0.4);
    vec3 finalColor = color * (ambient + lightColor * diffuse * attenuation);
    gl_FragColor = vec4(finalColor, 1.0);
}
user29112
  • 53
  • 1
  • 6

2 Answers2

2

If anyone's interested, I ended up finding the solution. Removing the calls to gl_NormalMatrix and gl_ModelViewMatrix solved the problem.

user29112
  • 53
  • 1
  • 6
0

The critical value here, lightPos, was being set as a function of vertexPos, which you have expressed in screen space (this happened because its original world space form was multiplied by modelView). Screen space stays with the camera, not anything in the 3D world. So to have a non-moving light source with respect to some absolute point in world space (like [4.0, 4.0, 4.0]), you could just leave your object's points in that space as you found out.

But getting rid of modelview is not a good idea, since the whole point of the model matrix is to place your objects where they belong (so you can re-use your vertex arrays with changes only to the model matrix, instead of burdening them with specifying every single shape's vertex positions from scratch).

A better way is to perform the modelView multiplication on both vertexPos AND lightPos. This way you're treating lightPos as originally a quantity in world space, but then doing the comparison in screen space. The math to get light intensities from normals will work out to the same in either space and you'll get a correct looking light source.

garett
  • 11
  • 1