dukey

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

http://www.lighthouse3d.com/opengl/glsl/index.php?dirlightpix

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.

http://i126.photobucket.com/albums/p95/dukeeeey/gfx%20stuff/directionallight.png

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"

"{\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"

"}\n";

char *fragmentShaderColour =

"varying vec4 diffuse,ambient;\n"

"varying vec3 normal,lightDir,halfVector;\n"

"void main()\n"

"{\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"

"}\n"

"color *= gl_Color;\n"

//

// test

//

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

"gl_FragColor = color;\n"

"}\n";

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

http://www.lighthouse3d.com/opengl/glsl/index.php?dirlightpix

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.

http://i126.photobucket.com/albums/p95/dukeeeey/gfx%20stuff/directionallight.png

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"

"{\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"

"}\n";

char *fragmentShaderColour =

"varying vec4 diffuse,ambient;\n"

"varying vec3 normal,lightDir,halfVector;\n"

"void main()\n"

"{\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"

"}\n"

"color *= gl_Color;\n"

//

// test

//

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

"gl_FragColor = color;\n"

"}\n";

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