So something came up today when I was going over my Blinn shader. As I've been taught, the half-angle vector is calculated in the fragment shader, and is equal to normalize(lightDir + viewDir). This seems to work fine.

When adding a normal map, this still seems to works, except I use tangent space vectors and dot the half-angle with the normal from the normal map.

But here's what I don't understand: when using normal maps, shouldn't the light & view directions be re-computed for each fragment? Seeing as the interpolation between the vectors is no longer linear, lightDir and viewDir can't possibly be correct anymore?

Somehow I feel like the per-pixel normal should play a part in calculating the view/light directions. Am I missing something?

This came up when working on a fresnel effect which also uses the half-angle vector. Without any changes to the half-angle vector, the fresnel effect can't possibly know anything about the normal map, which seems wrong (and actually looks wrong).

Here's the fresnel calculation:

 // Fresnel (Schlick approximation)
 float base = 1 - dot(viewDir, halfAngle);
 float exp = pow(base, 5);
 float fresnel = exp + fZero * (1.0 - exp);

Given that neither viewDir nor halfAngle incorporate the normals from the normal map, the fresnel effect is computed based on interpolated normals and looks "blocky". Maybe this isn't a problem for the Blinn computation, but I thought it might be too.

  • 1
    \$\begingroup\$ Why would the per-pixel normal affect the light/view directions? The light and camera are still at the same place, no matter which way the surface normal faces. As for your Fresnel effect, can't guess why it looks wrong without more context. \$\endgroup\$ Mar 21, 2014 at 6:43
  • \$\begingroup\$ Well, in the same way the vertices do not form a flat surface across the mesh (hence taking the light dir per-vertex), the pixels do not form a flat surface across the triangle, with bump mapping. I'll add info regarding the fresnel effect. \$\endgroup\$
    – cloudhead
    Mar 21, 2014 at 11:45

1 Answer 1


If you are computing the half-vector in the Vertex Shader and passing it to the Fragment Shader as an interpolated output, there is no guarantee that the normalized vector will remain unit length after being interpolated thru the triangle. So you should at least re-normalize it in the Fragment Shader.

  • \$\begingroup\$ This is how I learned it. \$\endgroup\$ Jun 25, 2014 at 7:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .