Unity 阴影

Posted by QXSoftware on March 20, 2017

Unity5 自带的阴影技术就是传统的阴影映射或者是屏幕空间的阴影映射。屏幕空间的阴影映射需要MRT(Multiple Render Targets)技术,有的移动端设备不支持这种技术。

渲染阴影还有很多别的方法,但是在目前的移动设备硬件条件下,最常用的就是阴影映射了。

传统的阴影映射(Shadow Map)

Shadow Map本质就是一张深度图(Z-Buffer),这个深度图是在光源空间下渲染需要投射阴影的物体,并且把这些物体的深度值渲染到深度图中,这个深度图就是阴影映射纹理。

使用阴影映射纹理技术进行阴影渲染的过程如下:

  • 在光源空间下渲染所有需要投射阴影的物体到阴影映射纹理
  • 正常渲染的过程中,将某一空间中的点映射到光源空间,取得其深度值,然后和从阴影映射纹理中取得的深度值进行比较,如果比阴影映射纹理中的深度值大,则说明这个点在阴影中;如果比阴影映射纹理中的深度值小,则说明这个点不在阴影中。

屏幕空间阴影映射(Screenspace Shadow Map)

屏幕空间阴影映射使用的技术可以说是传统阴影映射的一个变体。屏幕空间阴影映射需要MRT支持,它的工作方式是通过投射阴影的光源的阴影映射纹理和摄像机的深度图,计算出一个“阴影图”,后续的渲染直接从这个生成的“阴影图”中进行采样即可。

计算“阴影图”的过程和传统阴影映射类似,如果摄像机深度图中某个点的深度值比相对应的光源阴影映射纹理中的深度值大,则说明这个点在阴影中,否则不在阴影中。这个“阴影图”是屏幕空间下的。

半透明物体的阴影

通过上面的论述,我们知道了渲染阴影的基本原理。可以看到,阴影映射需要深度图,投射阴影的物体必须要写入深度值。

对于半透明物体,通常有Alpha TestAlpha Blend两种表现半透明的方式。Unity中默认的渲染不透明物体的ShadowCaster中没有任何关于透明度测试或者混合的逻辑,所以产生的阴影不会有透明度的变化。Transparent/Cutout/VertexLit中的ShadowCaster可以实现Alpha Test类型的透明阴影。

对于Alpha Blend类型的半透明物体,想要渲染他们的阴影是非常困难的一件事情,因为这些物体不写入深度。但是可以通过一些特殊的技巧来模拟阴影映射的过程。

阴影瑕疵(Shadow Acne)

阴影瑕疵的产生是由于阴影映射纹理的有限的分辨率造成的。这会导致阴影映射纹理中的一个像素实际对应于3D场景中的一片区域。所以单纯地解决这个问题可以尝试把阴影映射纹理的分辨率调大,当然这会导致内存消耗增加。

另一个办法就是增加Bias,这样可以简单地处理比较“平坦”的表面的阴影瑕疵问题。但是如果Bias设置的过大会发现物体的影子离开了自己,好像物体飘了起来。

acne 发音 [ˈækni] n. <医>痤疮,粉刺; 青春美丽痘; 粉剌;

参考资料:


转载请注明出处:

This work is licensed under a MIT License.