Directional light transformation in a shader

Started by
3 comments, last by The Blarg 14 years, 4 months ago
I implement lighting in a shader that uses a directional light which I pass as a uniform. The problem is I can't figure out how to transform it into eye space so that the lighting doesn't follow the camera. This is my vertex shader:

uniform vec3 lightDir;
uniform float ambient;
uniform vec3 lightColour;

void main()
{
    gl_Position = ftransform();

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);
    // Multiplying by gl_ModelViewMatrix seems ineffectual.
    // I also tried multiplying by gl_NormalMatrix, which didn't work either.
    vec3 realLightDir = normalize(vec3(gl_ModelViewMatrix * vec4(lightDir, 0)));

    float intensity = max(ambient, dot(eyeNormal, realLightDir));

    vec4 lightColourV4 = vec4(lightColour, 1.0);

    gl_FrontColor = gl_Color * lightColourV4 * intensity;
}
And these are the steps I take each frame:
  1. Enable the shader
  2. Set the shader's uniform variables
  3. Set the projection matrix (glMatrixMode(GL_PROJECTION); glLoadIdentity(); Set my projection)
  4. I do this each frame since I switch between projections a lot, e.g. perspective for the scene, orthographic for the HUD
  • Clear the modelview matrix (glMatrixMode(GL_MODELVIEW); glLoadIdentity();)
  • Position the camera with gluLookAt
  • Draw objects, rotating and translating as needed
  • Advertisement
    I had this exact same problem, and ended up getting more and more confused.

    I suggest outputting your vectors after they are multiplied (meaning you have to do it outside of the shader). Also output each matrix at each stage.

    It may sound tedious, but it will re-affirm any assumptions you might be making about how your calculations are going.

    Also, make sure your handedness and things like that are correct.

    vec3 eyeNormal = normalize(gl_NormalMatrix * gl_Normal);

    this line confuses me a bit... what normal is this from? the object you are rendering?

    ------------------------------

    redwoodpixel.com

    When passing the light direction how are you transforming it before you pass it as a uniform?
    You might try doing your steps 3, 4, and 5 (camera related) first before anything else. Then setup lights and shaders, the draw transforms, then draw.
    If you position your objects with a matrix, this really needs a separate model and view matrix. The easiest way is probably to perform all your calculations in world-space, and with separate model and view matrices, you can ignore the view matrix for the (diffuse) lighting calculations.
    You would declare this with uniform mat4 matView for example, in the shader, and set it with glUniformMatrix4fv.
    Well, isn't this confusing.

    The light vector is specified in world space. I have done no transformation on it outside the shader.
    The gl_Normal is from the object I'm rendering. All objects in my scene have normals for each vertex.

    Setting the direction uniform after I do my transformations seem to have no effect.

    So that you have a clearer picture, this is the actual code where I do the transformations:

    // Set shader uniforms// Light direction specified in world coordinates...glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(fovY, aspect, near, far);glMatrixMode(GL_MODELVIEW);glLoadIdentity();// Camera follows a spaceship that flies over the ground at a fixed height of 0.333 units// Camera is 2 units behind the ship and 1.333 units above the grounddouble radians = shipAngle * (3.14 / 180.0);gluLookAt(shipX - (2.0 * sin(radians)), 1.333, shipZ - (2.0 * cos(radians)), shipX, 0.333, shipZ, 0.0, 1.0, 0.0);// Draw the ground, which is centred at the origin...// Position the shipglTranslated(shipX, 0.333, shipZ);glRotated(shipAngle, 0.0, 1.0, 0.0);// Draw the ship...

    This topic is closed to new replies.

    Advertisement