UE中CSM(Cascaded Shadow Maps级联阴影)投影矩阵的构建


CSM中的参数虽然不多,但是对具体怎么工作的了解比较模糊,从追溯投影矩阵的构建过程可以加深对参数的理解。


首先阴影的平截头体(frustum)从近裁面开始,到设置的Shadow Distance结束,再按照Num Dynamic Shadow Cascades的数量将frustum切分成n份,比例是1 :Ex^1 : Ex^2... ,举例假设设置的Distribution Exponent是3的话,3级阴影的比例就是1:3:9。



实际边界会根据Transition的过渡区域进行偏移

将单独一级的阴影截体拿出来,从到近、远平面的距离和相机FOV以及纵横比的设置,我们可以构建出来近、远平面,从而得到近远平面的对角线长度。我们对frustum构建外接球时,这些数据可以帮我们求出球心,虚幻给出的公式是

b = (l1^2 - l2^2) / 2c+ c/ 2 ...DirectionalLightComponent.cpp l:722

我试了下就是 (l1/2)^2 + (c - b)^2 = (l2/2)^2 + b^2对b求解。



构建投影矩阵的时候会先求出world to light的矩阵,再用外接球的半径将light space中的xy归一化,然后有个主观的(写死了)轴向切换,tranfrom的距离也是直接用的半径。



以前自己写阴影的时候也卡在过投影矩阵上,虚幻的做法也只能说是最简单解,从阴影精度上来说明显不是最优解,在w,h的值选择和绕灯光方向旋转值选择上应该有更好的方案(比如视线和近远裁面平行的时候,w用截面距离明显利用率高过用外切球直径)。不过最小矩形包含平截头体的问题数学上似乎也不太好解,目前也没看到过相关的参考资料。

update:不计算最紧凑的包围体,是为了让包围体stable,以免造成shadow的抖动。