12
\$\begingroup\$

Why aren't normal maps just blue? I would think that normal maps should be predominantly blue in color because the Z component of the normal is represented by blue. Normals point out of the surface in the Z direction so we should see blue as the predominant colour since the Z component is dominant.

By definition tangent space is perpendicular to the surface. At any point we should have the normal always pointing in the Z (blue direction) with no X (red direction) or Y (green direction). Thus the normal map (since it is a "normal map") should have the colour of the normals which is just blue (R = x = 0, G = y = 0, B = z = 1) with no shades in between.

But normal maps are not so, and they have gradients of shades in them. Why is this so?

\$\endgroup\$

2 Answers 2

20
\$\begingroup\$

Tangent space is perpendicular to the geometric normals - the interpolated vertex normals of the polygons. The normal map provides the shading normals, relative to the tangent space defined by the geometric normals. When the shading normals are not the same as the geometric ones - i.e. because you have a detailed surface texture with features that are not modeled in the geometry - the normal map deviates from "flat blue" (RGB 128, 128, 255).

That's kind of the whole point of normal maps - they're the way you get the detailed, small-scale shape of a surface to be represented by lighting and shading even though you haven't modeled out all those tiny details with polygons.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ To elaborate, normal maps are generally done in tangent space as this stays accurate when the mesh is animated, whereas e.g. model-space normal maps would require the normal maps be animated in tandem with whatever animation you might have (which would be especially complicated with skeletons and arbitrary ragdolls, for example). For static geometry, there's no technical reason you couldn't have a model-space, not-all-blue normal map, simplifying your pixel shader ever so slightly (at the expense of consistency, requiring more shaders, and in turn requiring more shader selection changes). \$\endgroup\$ Commented Jul 3, 2012 at 6:55
  • 1
    \$\begingroup\$ (also normal map data typically can't be reused in multiple places on a mesh if in model space) \$\endgroup\$ Commented Jul 3, 2012 at 7:02
  • \$\begingroup\$ +1; the final para is key to the question - if the surface they were on was supposed to be completely flat, they would be blue. If the surface was supposed to have some roughness the normal map models that roughness without needing to specify extra geometry. \$\endgroup\$ Commented Jul 3, 2012 at 23:38
7
\$\begingroup\$

The simple answer is that it's because of range biasing.

Normals have a range -1,0 to 1.0, for each component (x,y,z). The normal map, stored as a 24 bit RGB image, on the other hand, has a range of 0 to 255 for each component.

This means that any components that were zero become 127.5 (the exact middle) in the normal map (which rounds to 128).

The normal vector (0,0,1) becomes (128,128,255) in the normal map image, which is a purplish color, rather than pure blue (0,0,255).

\$\endgroup\$

You must log in to answer this question.

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