阴影贴图适用于正射投影,但不适用于透视投影

问题描述

我已经实现了阴影贴图,并且只要我使用正交投影(例如从“太阳”获得阴影),它就可以很好地工作

但是,一旦我切换到聚光灯的透视投影,阴影贴图就不再对我有用。即使我使用完全相同的矩阵代码来创建(工作)透视相机投影,也是如此。

我不知道的透视阴影贴图是否存在一些陷阱?

此投影矩阵(正交)有效:

        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;
@H_502_10@

此投影矩阵(透视图)可以用作相机,但不能用于阴影贴图:

        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;
@H_502_10@

考虑到这当然是不现实的,正交投影会产生预期的光和影(请参阅下文)。

orthogonally projected light

要创建lightviewprojection矩阵,只需将投影矩阵与光变换的逆相乘即可。

对于透视相机来说一切正常,但对于透视(点)光却不能。

“不工作”是指:零光出现,因为某种原因,没有一个碎片落在光的视野内吗? (这不是纹理问题,而是变换问题。)

解决方法

这是在GLSL代码中缺少均匀W坐标除法的情况。

以某种方式,使用正交投影,不除以W就可以了。

对于透视投影,需要将光空间中的坐标除以W。