This question is about planar shadows as explained in Frank Luna's DX11 book. The author presents the 4x4 shadow matrix, whose bottom right element is n\$\cdot\$L (where n is the plane's normal and L is the light ray vector).

Projecting a shadow for a point P requires multiplying P by the shadow matrix, then dividing by the resulting w component (n\$\cdot\$L). He explains that the division is done as part of the perspective divide, however I fail to understand how it's carried out. Multiplying a projected shadow vertex by the perspective projection matrix overrides the vertex's w component with its z component. What am I missing here?


1 Answer 1


As mentioned in the question, the author makes a rather misleading statement:

Observe that this equation modifies the w-component so that sw=n\$\cdot\$L. Thus, when the perspective divide takes place, each coordinate of s will be divided by n\$\cdot\$L; this is how we get the division by n\$\cdot\$L using matrices.

(The equation in question is the planar shadow projection equation.)

Transforming a projected shadow vertex into clip space using the perspective projection matrix does indeed override the vertex's w component with its z component, thus knocking out the n\$\cdot\$L factor. Therefore it doesn't play a role in the perspective divide and doesn't get factored into the NDCs.

To see why this results in a correct projection, suppose that we transform a vertex using the shadow matrix, then divide by n\$\cdot\$L and transform the resulting point into clip space using the perspective projection matrix. (It doesn't matter if we do the division before or after the transformations since it's a scalar, and scalar-matrix multiplication is commutative.) We end up with the same clip space coordinates we would get if we didn't do the division, except all coordinates are divided by n\$\cdot\$L.

Since all clip space coordinates are divided by n\$\cdot\$L (including the w component), the perspective divide will simply cancel it out. In other words, we can simply ignore the n\$\cdot\$L as it plays no factor in perspective projection, and the resulting NDCs are correct as if we performed the division to begin with.


Since we ignore the n\$\cdot\$L, the intermediate clip space coordinates are actually incorrect (in a matter of fact, any intermediate representation such as world space and view space coordinates would also be incorrect. Only NDCs are correct). As explained in the last paragraph, correct clip space coordinates should all be divided by n\$\cdot\$L. The problem is that the hardware uses the clip space coordinates for some fixed-function ops such as clipping and perspective-correct interpolation.

n\$\cdot\$L could be negative depending on the angle between the vectors. Negative n\$\cdot\$L means the clip space z component will also be negative even if the shadow is projected in front of the camera (since if we had done the division, it would be positive). In this case the hardware will clip the vertex out. To prevent that, the L direction should be chosen such that it points towards the light source.

Additionally, the hardware uses the clip space w component for perspective-correct interpolation of vertex shader output attributes. Since this coordinate is incorrect if not divided by n\$\cdot\$L, interpolation ends up incorrect. Therefore care must be taken to do the division if such attributes are needed. But for planar shadows we should be fine if we don't do anything in particular because the normal used for lighting is constant anyway (because we project onto planes) and shadows are colored black such that all light calculations end up being zero regardless of input factors.


You must log in to answer this question.

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