0
votes

I have implemented shadow-mapping, and it works great as long as I use an orthogonal projection (e.g. to have shadows from 'sun')

However, as soon as I switched to a perspective projection for a spotlight, the shadowmap no longer works for me. Even though I use the exact same matrix code for creating my (working) perspective camera projection.

Is there some pitfall with perspective shadow maps that I am not aware of?

This projection matrix (orthogonal) works:

        const float projectionSize = 50.0f;

        const float left  = -projectionSize;
        const float right =  projectionSize;
        const float bottom= -projectionSize;
        const float top   =  projectionSize;

        const float r_l = right - left;
        const float t_b = top - bottom;
        const float f_n = zFar - zNear;
        const float tx = - (right + left) / (right - left);
        const float ty = - (top + bottom) / (top - bottom);
        const float tz = - (zFar + zNear) / (zFar - zNear);

        float* mout = sl_proj.data;

        mout[0] = 2.0f / r_l;
        mout[1] = 0.0f;
        mout[2] = 0.0f;
        mout[3] = 0.0f;

        mout[4] = 0.0f;
        mout[5] = 2.0f / t_b;
        mout[6] = 0.0f;
        mout[7] = 0.0f;

        mout[8] = 0.0f;
        mout[9] = 0.0f;
        mout[10] = -2.0f / f_n;
        mout[11] = 0.0f;

        mout[12] = tx;
        mout[13] = ty;
        mout[14] = tz;
        mout[15] = 1.0f;

This projection matrix (perspective) works as a camera, but fails to work with shadow map:

        const float f = 1.0f / tanf(fov/2.0f);
        const float aspect = 1.0f;
        float* mout = sl_proj.data;

        mout[0] = f / aspect;
        mout[1] = 0.0f;
        mout[2] = 0.0f;
        mout[3] = 0.0f;

        mout[4] = 0.0f;
        mout[5] = f;
        mout[6] = 0.0f;
        mout[7] = 0.0f;

        mout[8] = 0.0f;
        mout[9] = 0.0f;
        mout[10] = (zFar+zNear) / (zNear-zFar);
        mout[11] = -1.0f;

        mout[12] = 0.0f;
        mout[13] = 0.0f;
        mout[14] = 2 * zFar * zNear /  (zNear-zFar);
        mout[15] = 0.0f;

The ortho projection creates light and shadows as expected (see below) taking into account that it is not realistic of course.

orthogonally projected light

To create the lightviewprojection matrix, I simply multiply the projection matrix and the inverse of the light-transformation.

All working fine for perspective camera, but not for perspective(spot) light.

And with 'not working' I mean: zero light shows up, because somehow, not a single fragment falls inside the light's view? (It is not a texture issue, it is a transformation issue.)

1

1 Answers

0
votes

This was a case of a missing division by the homogeneous W coordinate in the GLSL code.

Somehow, with the orthogonal projection, not dividing by W was fine.

With the perspective projection, the coordinate in light-space needs dividing by W.