views:

1193

answers:

2

Hi

I try to implement point lights in OpenGL with GLSL. I send all the required data to the shaders. For simplicity I only use the diffuse light here.

My example shows a huge triangle which I want to illuminate with a single light source. The light source is shown as a small blue triangle.

For diffuse light I need to know the angle between the light and the surface. Therefore, I compute the normals and the light's direction. The dot-product will then give me a number between -1 and 1 whereas everything between 0 and 1 is illuminated.

However, here I am stuck because this angle is computed incorrectly in my example. Since it is hard to debug shaders, I used several outputs as the color of my surface. I used the normal as the color for the triangle and wherever the light was, the surface was always green. That is, the normals point up the y-axis and therefore they are computed right. That is, the light's direction must be wrong. However, I can't find the reason why it is wrong. The light's position and the vertex' position are passed in world space to the vertex shader, which then transforms them to eye space, compute the light's direction and pass this to the fragment shader:

vertex shader:

vec4 pos = modelview_matrix * <input vertex>;
vec4 lightPos = modelview_matrix * <light position>;

vec3 lightDir = normalize(lightPos.xyz - pos.xyz);

fragment shader:

float NdotL = max(dot(normalize(<correct normal>), normalize(lightDir)), 0.0);
gl_FragColor = vec4(1.0, NdotL, 0.0, 1.0);

I've appended some pictures of this example which definitely show, that the interpolation is really weird. I know want to know whether the code I pasted is correct or whether you need to know more of the code. FUrthermore, is this interpolation behaviour normal or is it a bug in my code?

http://img41.imageshack.us/img41/3566/interpolation.png http://img189.imageshack.us/img189/3566/interpolation.png

Especially the first picture shows that the center spot of the light is NOT directly under the light but slightly moved to the center of the triangle.

David Herrmann

Edit: I probably need to add that if I pass "pos" to the fragment shader (that is, it is interpolated) and then compute "lightDir" in the fragment shader, everything works fine.

A: 

I think that normalizing your lightDir in the vertex shader affects the result you get when interpolating the vectors because it takes the length out of the equation and thus affects the "speed" of the interpolation.

If you want a (visual) explanation, try to draw it in 2D on paper. First draw a line (your triangle) and a point (light source). Add two lines (lightDir) for both ends of the line to the light source and then shrink (normalize) those lightDir lines so that they have the same length and both meet at the light source. If you connect both ends of the normalized lightDir lines you will get a non-parallel line (if the light source isn't exactly in the middle of your first line). Now if you draw a line that goes exactly through the middle of one of the lines you will see that it doesn't go through the middle of the other line but will hit it a bit to the left or right.

Maurice Gilden
A: 

Take a look at the Lighthouse3D tutorial: http://www.lighthouse3d.com/opengl/glsl/index.php?pointlight

It provides a sample vertex and fragment shader that sets up a basic point light.

Eric