# Is Phong shading supposed to be so camera-angle dependent?

I'm not sure if I have a bug in my code or not. It seems like it's a bug, or at least a major shortfall. Here's two images of the same model at slightly different angles (by moving the camera):

As we can see, the diffuse shading is wildly different from moving the camera just a bit. I would expect this effect from the specular, but not the diffuse (and removing the specular component has no noticeable affect on this shading).

The relevant part of the fragment shader (which removing will remove this issue, but also remove all diffuse shading) is:

clamp(dot(normal, lightDir), 0, 1)


Where normal is the normalized normal vector in camera space (found with (VP * M * vec4(vertexNormal_modelspace,0)).xyz) and lightDir is the normalized light direction vector, which is found with:

vec3 vertexPosition_cameraspace = (VP * M * vec4(vertexPosition_modelspace, 1)).xyz;
eyeDirection_cameraspace = vec3(0, 0, 0) - vertexPosition_cameraspace;

vec3 lightPosition_cameraspace = (VP * vec4(lightPos, 1)).xyz;
lightDirection_cameraspace = lightPosition_cameraspace + eyeDirection_cameraspace;


The above clamped dot product is multiplied by the diffuse color and light color. It seems to be exactly what the Wikipedia page describes (they don't clamp it, but describe the need for it in the text).

Most of the Phong shading code is directly or heavily drawn from this site.

Is the Phong model supposed to result in such camera angle dependent diffuse shading? If not, any ideas as to what might be wrong? If so, what alternatives are there that don't have this effect?

What I want to achieve is essentially the diffuse shading, but without it changing on camera angle, which seems very unrealistic to me. Instead, only the angle between the light source and the normal would matter (and these don't change when we move the camera).

This is homework.

• It looks like the vertex normals might be messed up. Try having your fragment shader write out the received normal (using color = 0.5*normal + 0.5), and make sure it is consistent on flat planes and with other surfaces in the same orientation. – user41442 Mar 31 '15 at 4:27
• @Jason, the normal seem correct (screenshot with the shader using the colors you mentioned). As an aside, the shader applies to every model (there's about 25 in this scene). I take it from your comment that it shouldn't be like this, though, right? – Kat Mar 31 '15 at 5:07
• quick question, does VP stand for view-projection? because while your computations make sense if you use just the view matrix, i don't think they work if the projection matrix is involved (shading is typically computed in eye space or world space) – gemse Mar 31 '15 at 7:35
• Yes, it's the view matrix multiplied with the projection matrix. – Kat Mar 31 '15 at 7:44
• @gemse, you were correct. I changed it so that everything except the actual positions of vertices were not using the projection matrix (that is, they were computer in view space). This fixes the issue and achieves the intended result. If you convert your comment to an answer, I'll accept it. – Kat Mar 31 '15 at 8:23