What a height map actually does
Parallax, in cross-section
A height map changes no lighting term at all. It changes which texel you read. Cut the surface open and the reason is obvious: your eye is not looking straight down, so the point you can actually see is not the point directly beneath the pixel. Everything below is one slice through a surface, viewed from the side.
Cross-section through the surface
Drag left and right to move the pixel being shaded
the polygon — where the geometry really is
view ray
naive sample (straight down)
corrected sample (what you can see)
Pixel's own coordinate
—
Coordinate actually sampled
—
Offset applied
—
Texture lookups per pixel
—
The same surface, rendered
Controls
Push depth scale up and the one-step technique falls apart: it assumes the height under the pixel is the height everywhere along the ray, and that is only true for gentle bumps. Turn march steps down and steep parallax visibly terraces.
—
The one thing it still cannot do. Every technique here only shifts a texture coordinate before the lighting runs. The polygon is exactly where it always was — the blue line in the cross-section never moves. So the surface gains convincing depth in its interior and keeps a perfectly flat outline, which is why a parallax-mapped brick wall looks superb face-on and gives itself away the moment you can see its edge against the sky. Fixing that costs real vertices: displacement mapping or tessellation.