Reputation: 57
Well, I've been wrestling with implementing per-pixel lighting for a few days, and this is essentially the "result" I generally end up with.
I have these hard black spots throughout my mesh, and also those off-kilter dark spots. The blue shading "kind of" works right, except that it applies itself throughout the entire mesh and it appears to apply itself randomly as seen in the image. As I've bound the light to my camera, the light DOES "travel" across the mesh, albeit oddly most of the time. I have no idea why this is happening; my mesh data has normals that, as far as I can tell, are fine (no colour/smoothing issues in MilkShape, 3DS, Lightwave, Blender, Maya etc).
Here's my setup/light code:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
float lpos[4] = {get_cam_pos().x,get_cam_pos().y,get_cam_pos().z,1};
float lamb[4] = {0,0,1,1};
float ldiff[4] = {1,1,0,1};
float lspec[4] = {1,1,0.5,1};
GLfloat lin[4] = {5.0f,5.0f,5.0f,1};
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glLightfv(GL_LIGHT0, GL_AMBIENT, lamb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, ldiff);
glLightfv(GL_LIGHT0, GL_SPECULAR, lspec);
<from here camera matrix is then loaded and scene is rendered>
And here is my vert shader, from the Lighthouse3D per-pixel-light tutorial:
varying vec4 diffuse,ambientGlobal,ambient, ecPos;
varying vec3 normal,halfVector;
varying float dist;
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
/* first transform the normal into eye space and normalize the result */
normal = normalize(gl_NormalMatrix * gl_Normal);
/* compute the vertex position in camera space. */
ecPos = gl_ModelViewMatrix * gl_Vertex;
/* Normalize the halfVector to pass it to the fragment shader */
halfVector = gl_LightSource[0].halfVector.xyz;
/* Compute the diffuse, ambient and globalAmbient terms */
diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;
ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient;
ambientGlobal = gl_LightModel.ambient * gl_FrontMaterial.ambient;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
...and the frag shader, also from the Lighthouse3D tutorial:
uniform sampler2D color_texture;
varying vec4 diffuse,ambientGlobal, ambient, ecPos;
varying vec3 normal,halfVector;
varying float dist;
void main()
{
vec4 tex0Color = vec4(texture2D(color_texture,gl_TexCoord[0].st));
vec3 n,halfV,viewV,lightDir;
float NdotL,NdotHV;
vec4 color = ambientGlobal;
float att;
/* a fragment shader can't write a verying variable, hence we need
a new variable to store the normalized interpolated normal */
n = normalize(normal);
// Compute the ligt direction
lightDir = vec3(gl_LightSource[0].position-ecPos);
/* compute the distance to the light source to a varying variable*/
dist = length(lightDir);
/* compute the dot product between normal and ldir */
NdotL = max(dot(n,normalize(lightDir)),0.0);
if (NdotL > 0.0) {
att = 1.0 / (gl_LightSource[0].constantAttenuation +
gl_LightSource[0].linearAttenuation * dist +
gl_LightSource[0].quadraticAttenuation * dist * dist);
color += att * (diffuse * NdotL + ambient);
halfV = normalize(halfVector);
NdotHV = max(dot(n,halfV),0.0);
color += att * gl_FrontMaterial.specular * gl_LightSource[0].specular
* pow(NdotHV,gl_FrontMaterial.shininess);
}
gl_FragColor = tex0Color*color;
}
Upvotes: 1
Views: 1035