tutorial_shadow_mapping - seraph526/godot-se GitHub Wiki

阴影映射 (Shadow Mapping)

介绍

只是设置一盏灯到场景并不能足以模拟真实的效果。它只是在理论上给显卡提供了一种工作方式,光线不能到达的物体部分不会被照亮。 许多人(包括艺术家),都认为阴影是光线的投影,它们是由光线自己创造的黑暗区域,隐藏于光源之后的部分。

这个理论实际上不是正确的,理解阴影是光线不能到达的区域是很重要的。作为一种规则(不考虑间接光源),如果关闭一盏灯,原来的阴影区域还是会在那里。换句话说,阴影不是被填加到场景上的可见的物体,而是保持黑暗的一块区域。

Godot中的所有灯光类型都可以使用阴影贴图,所有都支持几种不同的技术以实现不同的渲染效率。阴影贴图使用一张存储了灯光的深度视图(depth view)纹理,在渲染时会检验每个像素。

阴影贴图的分辨率越大,阴影细节越高,但也会使用更多的内存和带宽(这也意味着帧率会下降)

灯光的阴影类型 (Shadows by Light Type)

平行光阴影 (Directional Light Shadows)

平等光会影响很大的区域。场景越大,影响的区域越大。如设置阴影贴图的分辨率保持不变,相同数量的阴影像素覆盖更大的区域,会导致块状阴影。出现了很多技术来解决这个问题,但最常用的是PSSM(六面体分割阴影映射(Parallel Split Shadow Maps))

这种技术将视图切分为2或4个部分,每个区域单独渲染。这样靠近的物体使用大的阴影,当物体远离时,使用更低细节的阴影,从一定意义上,这好像使得投影贴图的尺寸增加了,而实际上它并没有改变。当然这种技术也不是受约束的,分割越多,效率越低。在手机端,通常不要超过2个分割。

另一个技术是PSM(透视阴影映射(Perspective Shadow Mapping)).这个技术比PSSM的消耗比PSSM要低(和正交(orthogonal)差不多),但它只在一定的入射光角度下正常工作。也就是说,PSM只在摄相机方向和光的方向都固定时才有用,当光线与摄相机平行时不工作(此时PSM完全不工作)

泛光灯阴影 (Omni Light Shadows)

全方向的光源有一些麻烦。如果用一张纹理代表360度的光?有两种选择,第一种是使用DPSM(双抛物面阴影映射(Dual Paraboloid Shadow Mapping))。这种技术速度很快,但要使用显卡(DISCARD)(这使得它在mobile上没多大用途)。如果几何体的精度不够,DPSM的效果会相当差,所以如果几何体看起来不是很紧密,就需要更多的顶点,第二个选项是简单的不使用阴影贴图,而是使用阴影立方体贴图。这样速度很快,但是需要六通渲染所有的方向,在目前的GLES2渲染上还不支持。

聚光灯阴影 (Spot Light Shadows)

聚光灯阴影比较简单,只是需要一张纹理及可,不需要特别的技术。

阴影参数 (Shadows Parameters)

实际上,阴影只有一张纹理通常会有一些问题。最常见的就是Z轴排序(物体边缘线会投射阴影。有两个方法解决此问题,第一个方法是修改offset参数,第二个方法是使用过滤阴影算法,通常效果不错,而且没有更多的小问题,但是会消耗更多的GPU).

调用Z-Offset (Adjusting Z-Offset)

如果你决定要使用速度更快的无过滤阴影模式,如果想要获得更多的细节或者你喜欢性感的锯齿状的阴影边缘,因为这使你想起了精典的前一代游戏。真像是这是一种伤害,但是,大部分情况下,此问题是可以解决的,可以使它看起起更好一些。没有魔法数字,每个场景你会得到不同的显示效果,只是调节一些参数,让我们一步一步开始吧:

首先,打开阴影,我们假设Z-Offset和Z-Slop-Scale的值都是0,你会得到如下效果:

所有的self-shadowings都消失了!除了有些问题。。。哦,好吧。继续调节,阴影已经不在它们的投射物体上了,这效果看起来十分糟糕。好吧,让我们把参数调节回来。

现在Z-Slop-Scale闪亮登场。此设置使阴影投射物体变薄,所以边框不再有self-shadow:

好吧,差不多了,阴影投射物体太薄了,看起来不是很好。如果运气好的话,前面的设置效果会很不错,让我们接受这并不存在的完美,再来看些别的东西.

阴影过滤 (Shadow Filtering)

原始阴影是块状的。增加分辨率会让块变小,但仍然是块状的。 Godot提供了一些方式可以过滤它们(例子中的阴影是为了需要故意做的低分辨率):

ESM是复杂些的过滤,有一些调节参数。ESM使用阴影模糊(模糊通道的数量,乘数可以调节).