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.