c++mathopenglglm-mathshadow-mapping

light view matrix in stable cascaded shadow mapping


I have recently implemented cascaded shadow maps and make it stable by following this post. Now everything works, except that when I move directional light to the top mid of the world, the shadow suddenly turns all dark. With some debugging I find that the light view matrix is causing the problem.

This is how I compute the view matrix:

glm::mat4 view = glm::lookAt(
    center + lightDirNorm * nearOffset,
    center,
    camera.worldUP
);

center is the bounding sphere center, worldUP is a constant value of vec3(0.0, 1.0, 0.0), lightDirNorm is the normalized light direction from world origin to light position.

When I move light position to vec3(0.0, 20.0, 0.0), lightDirNorm becomes vec3(0.0, 1.0, 0.0). In this case, view direction is in the same line as worldUP vector. As a result, it is not possible to do cross product and compute the right vector. This is bothering because it is a common light direction.

Because the shadow is stable, the worldUP vector used here has to be something constant. The only workaround I could think of is to add a small offset to the worldUP vector, to make it like vec3(0.00001, 1.0, 0.0).

I'm wondering if there are better ways to handle that?


Solution

  • "Making it stable" is not applicable to a light source whose direction changes. The stability refers to the camera movement while the light source is stationary. Consequently you can choose any orthogonal up vector as a function of the lightDirNorm, and it will keep your shadows stable.

    I'd also suggest staying away from any lookAt functions. Instead specify your light direction by azimuth and altitude, and use rotation matrices to calculate the view matrix without any danger of singularities.