How to transform directional light to camera space in GLSL

Aaron picture Aaron · Dec 11, 2009 · Viewed 11.2k times · Source

I have the following GLSL code for lighting:

uniform vec3 lightDir; // Parallel light
uniform float ambient;
uniform vec3 lightColour;

void main()
{
     gl_Position = ftransform();

     vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
     float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));

     gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity;
}

The light vector is specified in world space. I set the camera orientation and position using gluLookAt. Since OpenGL assumes the light vector is in camera space, the light moves with the camera instead of staying in a fixed orientation.

I tried activating the shader and setting the light vector both before and after I call gluLookAt, but I get the same effect. What exactly do I have to do to properly transform the light vector?

Answer

rioki picture rioki · Mar 5, 2010

You have a common problem, often seen in GLSL tutorials online. You are passing your lighting values via uniform. Why don't you use the glLight calls, like with fixed function rendering, and pull the values from gl_LightSource[n]. The difference is that openGL will automatically translate everything in view space.

void main()
{
    // remember: directional lights are GL_POSITION with w = 0
    vec3 lightDir = vec3(gl_LightSource[0].position); 
    float ambient = gl_LightSource[0].ambient;
    vec3 lightColour = vec3(gl_LightSource[0].diffuse);


    gl_Position = ftransform();

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
    float intensity = max(ambient, dot(eyeNormal, normalize(-lightDir));

    gl_FrontColor = gl_Color * vec4(lightColour, 1.0) * intensity;
}

A always great resource on the subject: http://www.lighthouse3d.com/opengl/glsl/index.php?lights

And always useful is the GLSL Cheat Cheat: http://www.cs.brown.edu/courses/cs123/resources/glslQuickRef.pdf