views:

818

answers:

4

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?

A: 

The problem in you shader, is that you have eye space normals, and worldspace lights.

I'm not sure, but transforming your light vector by your normal matrix should fix the problem.

Or, to be more efficient, you can transform the light vec in object-space (in program code), then no transformation for each normal is requiered.

Tryum
I tried multiplying lightDir by gl_NormalMatrix in the shader and there was no effect.I also tried multiplying by gl_ModelViewMatrix, like this: `vec3 lightEyeDir = normalize(vec3(gl_ModelViewMatrix * vec4(-lightDir, 1.0)));`Doing this knocked out the diffuse contribution completely.For transforming the light vector in program code, what transformation would I do exactly?
Aaron
By transforming the light dir by the inverse model matrix, you should obtain a model-space light.
Tryum
MaR
A: 

the code in shader calculates directional light which does not change with the position of light, so you should use spotLight or pointLight functions.

Try to find shaders for these light sources. if you can not find, tell me so i will send you one.

ufukgun
+1  A: 

You must decide in which space you will do the lighting. If you want to follow "standard" OpenGL then it is view space. Your light vector must then be rotated by rotation part of the view matrix before passing to a shader (imho simplest solution).

You can also apply lights in other spaces (tangent, object, world or even screen space - for deffered shading) but that's different topic. Also note that for advanced use you will need to forget OpenGL and do everything with your own matrices and shaders (no default lighting/transformation stuff).

MaR
+2  A: 

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

Sean Farrell