阴影(Shadow Mapping)
着色是一种局部现象,只考虑着色点自己、光源、摄像机,如果我要算出它的着色,完全不考虑其它物体,甚至自己的其它部分对这个着色点的影响。而事实上如果有其它物体挡在 shading point 的光源之间,那就会挡住光线,光线就到达不了 shading point,这就是为什么会有阴影,我们之前说着色解决不了阴影,我们现在就来解决这个问题。
Shadow Mapping 本质上是一种图像空间的做法,所谓图像空间就是说,我在生成阴影的这一步,我是不需要知道场景的几何信息的。Shadow Mapping 也会导致走样现象。
关键思想在于,如果这个点不在阴影里,你从摄像机可以看到这个点,光源也可以看到这个点。
经典的 Shadow Mapping 只能处理点光源,这种阴影通常有很明显的阴影的边界,要么在阴影里要么不在阴影里,这种阴影我们叫硬阴影。
有两步操作。第一,先从光源看向整个场景,也就是说在光源处有一个虚拟的摄像机在这里,我先做一个光栅化。
我们得到的这个图我们不要做着色,我们把这些点对应的位置的深度记下来。相当于我只需要它的深度图。
第二步,我们用真正的摄像机位置再次看向这个场景
找到对应的点投影回光源,在光源中的深度图上应当出现在哪个位置上。
在深度图上对于这个点记录有一个深度,我同样可以计算从摄像机看这个点,这个点到光源的深度,这两个深度肯定是一致的,那说明这个点一定是可以被光源所看到的。
而下面的这个点深度不一样,就看不到了。
从实例来看:
从光源看向场景。
记录深度缓存。
投影回光源生成的 Shadow Map 上。会有浮点数精度问题,并且一个像素覆盖的范围会有一定误差,所以呈现这样,即使不判相等,通过设置范围、加 bias 偏差等方法都不能本质上解决问题。
这个 Shadow Map 本身是有分辨率的,那这个分辨率要多大?如果我用的 Shadow Map 分辨率很低,而我渲染的场景分辨率又非常高,那么说我记录的阴影的信息是走样的,那就会投影出一个有锯齿的阴影,那就会很难看。而用分辨率很高的 Shadow Map 效果当然非常好,但是开销就会非常大。
现在当然会有更大的开销,要渲染整个场景两遍,原先只做 shading 只要渲染一遍。
即使这样,也不耽误成为现在几乎所有 3D 游戏、3D 电影的主流技术。
Shadow Map 的缺陷:
硬阴影 VS 软阴影
软阴影其实在物理上就是所谓的半影(Penumbra)。
对于点光源确实不可能出现软阴影,如果有软阴影,那么就说明光源有一定的大小。