EDIT
The problem turned out to be a combination of things, but most importantly I was miscalculating lighting intensities because I wasn't correctly calculating my normal matrix. The fix has left my memory since some time ago now, but I remember I was not taking the transpose-inverse, and that helped a great deal in solving the problem.
I've spent some time working on this problem, but I can't for the life of me figure it out.
I figured out that, when applying multiple light sources to an object, you must clamp the final color values after summing them together, but I'm still getting weirdly dark edges when the lights interact.
Here's a screenshot of what I'm describing:
There's a head light that faces in the direction of the current camera and another light source to the far left of the scene. The headlight is currently centered just to the right of the teapot's knob/handle, and as you can see, there's some pretty strange interaction going on.
Here's my shader source:
vertex shader
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec4 a_normals;
varying vec4 v_color_or_normal;
varying vec3 cam;
varying vec3 vert;
uniform mat4 u_xformMatrix;
uniform mat4 u_cameraMatrix;
void main() {
gl_Position = u_cameraMatrix * u_xformMatrix * a_position;
v_color_or_normal = a_color;
cam = vec3(u_cameraMatrix * u_xformMatrix * a_position);
vert = vec3(a_position);
}
fragment shader
precision mediump float;
varying vec4 v_color_or_normal;
varying vec3 cam; //modelview_mat*vertex
varying vec3 vert;//just the vertex
uniform int renderMode; //pass 0 when rendering the ground, 1 when rendering the teapot
uniform vec3 lookVec; //pass the vector representing the camera direction
uniform mat4 u_normalMatrix; //the normal matrix for calculating normals
//I'm using
//u_normalMatrix = modelMatrix.invert().transpose() (the transpose inverse)
uniform vec3 camCoords; //headlight origin
uniform vec3 worldLightCoords; //fixed light origin
void main() {
vec3 emissive = vec3(0.0, 0.0, 0.0); //my professor requires this. Not sure why.
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shiny;
vec3 normal;
if(renderMode == 0) { //render the ground colors
ambient = vec3(v_color_or_normal - vec4(0.05, 0.3, 0.05, 0.0));
diffuse = vec3(0.05, 0.3, 0.05);
specular = vec3(0.22, 0.22, 0.22);
shiny = 4.0;
normal = vec3(normalize(u_normalMatrix * vec4(0.0, 1.0, 0.0, 1.0)));
}
if(renderMode == 1) { //render the teapot colors
//do stuff for teapot
ambient = vec3(0.105882, 0.58824, 0.113725);
normal = vec3(normalize(u_normalMatrix * v_color_or_normal));
diffuse = vec3(0.427451, 0.470588, 0.541176);
specular = vec3(0.22, 0.22, 0.22);
shiny = 9.0;
}
vec3 worldLightPos = worldLightCoords;
vec3 camLightPos = camCoords;
vec3 fixedLightDirection = normalize(worldLightPos - vert);
vec3 camLightDirection = normalize(lookVec - vec3(0,0,10.0));
//calculate diffuse/spec for fixed light source
float lambertianFix = max(dot(fixedLightDirection, normal), 0.0);
float specFix = 0.0;
if(lambertianFix > 0.0) {
vec3 R = reflect(-fixedLightDirection, normal);
vec3 viewDirection = normalize(-vert);
float specularAngle = max(dot(R, viewDirection), 0.0);
specFix = pow(specularAngle, shiny);
}
vec3 total_diffuse = lambertianFix*diffuse;
vec3 total_specular = specFix*specular;
//calculate diffuse/spec for headlight
float lambertianCam = max(dot(camLightDirection, normal), 0.0);
float specCam = 0.0;
if(lambertianCam > 0.0) {
vec3 R = reflect(-camLightDirection, normal);
vec3 viewDirection = normalize(-cam);
float specularAngle = max(dot(R, viewDirection), 0.0);
specCam = pow(specularAngle, shiny);
}
total_diffuse += lambertianCam*diffuse;
total_specular += specCam*specular;
//clamp values
total_diffuse = clamp(total_diffuse, 0.0, 1.0);
total_specular = clamp(total_specular, 0.0, 1.0);
//put it all together
gl_FragColor = vec4(emissive + ambient + total_diffuse + total_specular, 1.0);
}
Any help is much appreciated. Thanks!