阴影
Unity 的灯光可以将 阴影 从一个游戏对象投射到自身的其他部分或是附近的其他游戏对象上。阴影以『扁平』的方式体现游戏对象的尺寸和位置,因此可以为场景添加一定程度的深度和真实感。
场景视图中的游戏对象正在投射阴影
阴影如何工作?
考虑一种最简单的情况,在场景中只有单个光源。光线从光源出发并沿着直线传播,最终可能会碰撞到场景中的游戏对象。一旦光线碰撞到某个游戏对象,光线将无法继续传播和照亮前方的任何其他游戏对象(例如,光线无法通过第一个游戏对象,并从该游戏对象上反弹离开)。游戏对象投射的阴影不过是一些不被照亮的区域,因为光线无法到达这些区域。
观察阴影的另一个方式是,想象在光源位置处有一个摄像机。场景中的阴影区域恰好是摄像机无法看到的区域。
A “light’s eye view” of the same scene 同一场景中,光源位置的眼睛所看到的视图
事实上,这正是 Unity 确定阴影位置的方式。光源使用与摄像机相同的原理,来『渲染』光源视角范围内的场景。光源像摄像机一样使用一个深度缓存系统,持续跟踪面向光源的表面;只有位于视线中的表面接受光照,其他所有表面则都在阴影中。这里的深度映射称为 阴影映射(你可以在阴影映射的 维基百科页 中找到更多信息)。
开启阴影
使用检视视图中的 Shadow Type 属性来开启和定义来自单个光源的阴影。
Shadow Type 阴影类型
选项 Hard Shadows 产生具有尖锐边缘的阴影。与 Soft Shadows 相比,它不是特别逼真,但是只涉及较少的计算,并且对于大多数场合是可接受的。Soft Shadows 则可以减少阴影纹理的『块状』混叠效应。
Strength 阴影强度
决定阴影的暗度。一般来说,某些光线会被大气层散射,和被其他游戏对象反射,所以通常不希望阴影被设置为最大暗度。
Resolution 阴影分辨率
设置阴影纹理在『摄像机』上的的渲染分辨率。如果阴影具有非常明显的边缘,那么可能需要增大该值。
Bias 阴影偏差
微调阴影的位置和定义。相关详细信息,请参阅下面的 阴影映射和偏差属性 Bias。
Normal Bias 阴影法线偏差
微调阴影的位置和定义。相关详细信息,请参阅下面的 阴影映射和偏差属性 Bias。
Shadow Near Plane 阴影近剪裁平面
允许在渲染阴影时选择近剪裁平面的 Near 值。如果游戏对象到光源的距离小于该值,这不会投射任何阴影。
场景中的每个 网格渲染器 Mesh Renderer 还具有 投射阴影 Cast Shadows 和 接收阴影 Receive Shadows 属性,它们必须按需开启。
在 投射阴影 Cast Shadows 的下拉菜单中选择 On 或 Off 可以开启或禁用该网格投射阴影。或者选择 Two Sided,以允许表面的两面都投射阴影(此时,背面剔除被忽略);或者选择 Shadows Only,以允许一个不可见的游戏对象投射阴影。
阴影映射和偏差属性 Bias
光源的阴影在渲染最终场景期间被确定。当场景被渲染到主摄像机视图时,视图中每个像素的位置被转换为光源坐标。比较表面像素和阴影纹理中像素距光源的距离。如果表面像素的距离更远,那么表面像素可能被它与光源之间的另一个游戏对象所遮挡,所以它不会被照亮。
正确的投影
被光源直接照亮的表面,有时看起来部分位于阴影中。这是因为位于阴影中特定距离的像素,有时被计算为更远(这是使用了阴影过滤,或是为阴影纹理设置了低分辨率图像)。最终,位于阴影中的像素上的图纹,原本应该被真正照亮,却产生了成为了『阴影痤疮』的视觉效果。
错误的自投影产生了阴影痤疮
为了防止阴影痤疮,可以让阴影纹理的距离加上 Bias 值,以确保位于边界的像素通过距离比较,或者,在渲染阴影纹理时,稍微修正游戏对象的法线。当开启阴影时,这些值可以通过灯光检视视图中的 阴影偏差 Bias 和 阴影法线偏差 Normal Bias 属性设置。
不要将 阴影偏差 Bias 设置的太大,因为阴影周围靠近游戏对象的区域有时会被错误地照亮。从而导致阴影和游戏对象分离,使得游戏对象看起来好像是在地面上空飞行。
阴影偏差 Bias 过大,使得阴影与游戏对象分离。
同样地,阴影法线偏差 Normal Bias 过大,会使阴影相比游戏对象显得太窄:
阴影法线偏差 Normal Bias 过大,使得阴影的形状太窄
在某些情况下,阴影法线偏差 Normal Bias 可能导致称为『光线泄漏』的意外效果,光线穿过相邻的几何体,泄漏到被遮盖的区域。一个可行的解决方案是,打开游戏对象的 网格渲染器 Mesh Renderer,修改 Cast Shadows 属性为 Two Sided。但是这个方案可能需要更多的计算资源,增加渲染场景时的性能开销,尽管它在某些情况下确实有效。
为了避免发生这种意外效果,光源的阴影偏差可能需要调整。通常,通过眼睛来判定正确的偏差值更容易些,而不是尝试通过计算获得。
为了进一步防止阴影痤疮,我们使用了一种成为『阴影着陆』的技术(参见 平行光阴影:阴影着陆)。通常,这种技术是有效的,并且可以为非常大的三角形创建人为的视觉效果。
设置较低的 阴影近剪裁平面偏移 Shadow near plane offset 值,导致阴影中的孔状效果。
调整 阴影近剪裁平面偏移 Shadow Near Plane Offset 属性,可以解决这个问题。该值太大,也会导致阴影痤疮。
正确的投影