GAME202笔记汇总
3. Real-Time Shadow
3.1 Shadow Mapping
Shadow Mapping 是生成阴影的常用方法(塞尔达或者电影玩具总动员1都用的这种方法):
- 先从光源进行光栅化,得到“光源可视深度图”
- 再从摄像机进行渲染并利用“光源可视深度图”得到最终渲染结果
这样的方式不需要过多了解场景的几何结构,速度比较快。
但与此同时也有其问题,比如锯齿化和自遮挡现象
先从光源进行渲染,的到光源深度图
再从摄像机进行场景渲染,比较像素和光源的距离与光源深度图上对应像素的深度。如果发现一致,则未遮挡,否则视作遮挡。
Shadow Mapping 实现比较容易,且能得到还不错的效果。
并且从图也能看出,阴影对于渲染效果的影响是非常大的(为视觉提供相对位置关系的信息)
对光源深度图进行灰阶可视化
摄像机对应的每个像素的光源深度可视化效果
3.2 Issues in Shadow Mapping
可能会在平滑的表面渲染出阴影的纹路,即自遮挡现象
其原因主要是“光源深度图”的一个像素可能会覆盖很大一片区域,如果光源和表面法线的夹角很大,则会导致摄像机检索一个像素时很可能得到误差较大的结果,进而错误地认为此像素被遮挡
容易想到的解决这个问题的方案是判断距离时加一个误差区间(工业界一般就是用这种方法)。
确实可以一定程度解决自遮挡问题,但也会带来新的问题:阴影和实体脱离。
学术界还有另外一种处理方法:在生成 Shadow Map 时,不仅保存最小深度,同时也保存次小深度,最后在比较时使用其平均值。
但工业界之所以没人用,主要是因为其几个问题:
- 需要模型是封闭的,不能是一个平面
- 同时取最小和次小深度的算法复杂度略高于仅取最小
Shadow Mapping 的另外一个问题就是锯齿化
当然锯齿化也可以用超采样,提高阴影图的分辨率等方法来改善,但也对应着更高的计算量。
3.3 The Math behind Shadow Mapping
微积分中的两个基本不等式
可以把不等式改成约等时,并且在下面情况下两边是相近的:
- \(g(x)\) 的支撑集非常小
- \(g(x)\) 函数变化不太大
有了这个约等式,我们就可以用它来简化渲染方程。
首先可以把 Visibility 项拆出来。
这其实就是 Shadow Map 的思路,先做 Shading,再根据 Visibility 进行一个比例乘
所以也可以回过来分析 Shadow Mapping 的适用性:
- 在点光源时比较有效
- 对 radiance 变化不大的面光源 渲染漫反射表面时比较有效
3.4 Soft Shadow
但用 Shadow Map 做出来的硬阴影其实在现实中并不常见。
现实中更多时软阴影。
而软阴影主要是因为光源被部分遮挡导致的
- 现实中不存在点光源,所以总能被部分遮挡