View Full Version : Directional light problems

01-01-2011, 06:04 AM
I am trying to use directional light. My shader is essentially the same as the one from the lighthouse tutorial


But it produces some artifacts at certain angles.

Namely I get a black streak. This shouldn't happen at all, as it should be lit as the ambient light colour, like the rest of the back of the model.


The left shows the problem, the right shows the model rotated slightly, which makes the problem disappear.

My shader is this

char *vertexShaderColour =
"varying vec4 diffuse,ambient;\n"
"varying vec3 normal,lightDir,halfVector;\n"

"void main()\n"
/* first transform the normal into eye space and normalize the result */
"normal = normalize(gl_NormalMatrix * gl_Normal);\n"

/* now normalize the light's direction. Note that according to the
OpenGL specification, the light is stored in eye space. Also since
we're talking about a directional light, the position field is actually
direction */
"lightDir = normalize(vec3(gl_LightSource[0].position));\n"

/* Normalize the halfVector to pass it to the fragment shader */
"halfVector = normalize(gl_LightSource[0].halfVector.xyz);\n"

/* Compute the diffuse, ambient and globalAmbient terms */
"diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;\n"
"ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;\n"
"ambient += gl_LightModel.ambient * gl_FrontMaterial.ambient;\n"

"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
"gl_FrontColor = gl_Color;\n"


char *fragmentShaderColour =
"varying vec4 diffuse,ambient;\n"
"varying vec3 normal,lightDir,halfVector;\n"

"void main()\n"
"vec3 n,halfV,viewV,ldir;\n"
"float NdotL,NdotHV;\n"
"vec4 color = ambient;\n"

/* a fragment shader can't write a verying variable, hence we need
a new variable to store the normalized interpolated normal */
"n = normalize(normal);\n"

/* compute the dot product between normal and ldir */
"NdotL = max(dot(n,lightDir),0.0);\n"

"if (NdotL > 0.1) {\n"
"halfV = normalize(halfVector);\n"
"NdotHV = max(dot(n,halfV),0.0);\n"
"color += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV,gl_FrontMaterial.shininess);\n"
"color += diffuse * NdotL;\n"

"color *= gl_Color;\n"

// test
"color.rgb = pow(vec3(color), vec3(1.0 / 4.2));"

"gl_FragColor = color;\n"

I ramped up the brightness at the end to make the problem more obvious.

Dark Photon
01-01-2011, 10:49 AM
Why are you only adding directional light when N*L > 0.1? When N*L in 0.0..0.1, you're only adding ambient. I suspect those fringes might have N*L in 0.0..0.1.

Also, don't understand why you're normalizing the half vector in both vtx and fragment, and passing it in as a varying. You're obviously not doing local-viewer, so eye vector, directional light vector, and directional light half-vector are constant (uniform). Same thing with the light vector (it's a constant). Shouldn't cause problems ... just appears superfluous. Also don't understand why you're eating varyings for ambient and diffuse? Those are constants as well.

Also, I'd remove this line. Looks fishy:

* color.rgb = pow(vec3(color), vec3(1.0 / 4.2))

Another thing I notice is that you're using the alpha from more than just the diffuse material. Fixed function pipe just uses the diffuse alpha. For testing, try setting color.a to 1. Or just set to diffuse.a

01-01-2011, 11:39 AM
>> * color.rgb = pow(vec3(color), vec3(1.0 / 4.2))

was just to brighten up the final image

>> if (NdotL > 0.1)
just testing, meant to be 0

I figured out what was causing the problems

When NdotHV is 0, the values come out black ! As for the rest of the points, its the same as the tutorial, but I guess it has some issues with it. I haven't even thought about the alpha part to be honest.