Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GLSL lighting code shift the light spot with the camera?

I am trying to make a custom light shader and was trying a lot of different things over time. Some of the solutions I found work better, others worse. For this question I'm using the solution which worked best so far.

My problem is, that if I move the "camera" around, the light positions seems to move around, too. This solution has very slight but noticeable movement in it and the light position seems to be above where it should be.

Default OpenGL lighting (w/o any shaders) works fine (steady light positions) but I need the shader for multitexturing and I'm planning on using portions of it for lighting effects once it's working.

Vertex Source:

varying vec3 vlp, vn;

void main(void)
{
    gl_Position = ftransform();

    vn = normalize(gl_NormalMatrix * -gl_Normal);
    vlp = normalize(vec3(gl_LightSource[0].position.xyz) - vec3(gl_ModelViewMatrix * -gl_Vertex));

    gl_TexCoord[0] = gl_MultiTexCoord0;
} 

Fragment Source:

uniform sampler2D baseTexture;
uniform sampler2D teamTexture;
uniform vec4 teamColor;

varying vec3 vlp, vn;

void main(void)
{
    vec4 newColor = texture2D(teamTexture, vec2(gl_TexCoord[0]));
    newColor = newColor * teamColor;
    float teamBlend = newColor.a;

    // mixing the textures and colorizing them. this works, I tested it w/o lighting!
    vec4 outColor = mix(texture2D(baseTexture, vec2(gl_TexCoord[0])), newColor, teamBlend);

    // apply lighting
    outColor *= max(dot(vn, vlp), 0.0);
    outColor.a = texture2D(baseTexture, vec2(gl_TexCoord[0])).a;

    gl_FragColor = outColor;
}

What am I doing wrong?

like image 292
Cobra_Fast Avatar asked Jun 17 '11 21:06

Cobra_Fast


1 Answers

I can't be certain any of these are the problem, but they could cause one.

First, you need to normalize your per-vertex vn and vlp (BTW, try to use more descriptive variable names. viewLightPosition is a lot easier to understand than vlp). I know you normalized them in the vertex shader, but the fragment shader interpolation will denormalize them.

Second, this isn't particularly wrong so much as redundant. vec3(gl_LightSource[0].position.xyz). The "position.xyz" is already a vec3, since the swizzle mask (".xyz") only has 3 components. You don't need to cast it to a vec3 again.

like image 143
Nicol Bolas Avatar answered Oct 03 '22 19:10

Nicol Bolas