阴影

Unity 的灯光可以将 阴影 从一个游戏对象投射到自身的其他部分或是附近的其他游戏对象上。阴影以『扁平』的方式体现游戏对象的尺寸和位置,因此可以为场景添加一定程度的深度和真实感。

Scene with objects casting shadows

场景视图中的游戏对象正在投射阴影

阴影如何工作?

考虑一种最简单的情况,在场景中只有单个光源。光线从光源出发并沿着直线传播,最终可能会碰撞到场景中的游戏对象。一旦光线碰撞到某个游戏对象,光线将无法继续传播和照亮前方的任何其他游戏对象(例如,光线无法通过第一个游戏对象,并从该游戏对象上反弹离开)。游戏对象投射的阴影不过是一些不被照亮的区域,因为光线无法到达这些区域。

阴影 - 图2

观察阴影的另一个方式是,想象在光源位置处有一个摄像机。场景中的阴影区域恰好是摄像机无法看到的区域。

A lights eye view of the same scene

A “light’s eye view” of the same scene
同一场景中,光源位置的眼睛所看到的视图

事实上,这正是 Unity 确定阴影位置的方式。光源使用与摄像机相同的原理,来『渲染』光源视角范围内的场景。光源像摄像机一样使用一个深度缓存系统,持续跟踪面向光源的表面;只有位于视线中的表面接受光照,其他所有表面则都在阴影中。这里的深度映射称为 阴影映射(你可以在阴影映射的 维基百科页 中找到更多信息)。

开启阴影

使用检视视图中的 Shadow Type 属性来开启和定义来自单个光源的阴影。

阴影 - 图4

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 的下拉菜单中选择 OnOff 可以开启或禁用该网格投射阴影。或者选择 Two Sided,以允许表面的两面都投射阴影(此时,背面剔除被忽略);或者选择 Shadows Only,以允许一个不可见的游戏对象投射阴影。

阴影映射和偏差属性 Bias

光源的阴影在渲染最终场景期间被确定。当场景被渲染到主摄像机视图时,视图中每个像素的位置被转换为光源坐标。比较表面像素和阴影纹理中像素距光源的距离。如果表面像素的距离更远,那么表面像素可能被它与光源之间的另一个游戏对象所遮挡,所以它不会被照亮。

Correct shadowing

正确的投影

被光源直接照亮的表面,有时看起来部分位于阴影中。这是因为位于阴影中特定距离的像素,有时被计算为更远(这是使用了阴影过滤,或是为阴影纹理设置了低分辨率图像)。最终,位于阴影中的像素上的图纹,原本应该被真正照亮,却产生了成为了『阴影痤疮』的视觉效果。

Shadow acne in the form of false self-shadowing artifacts

错误的自投影产生了阴影痤疮

为了防止阴影痤疮,可以让阴影纹理的距离加上 Bias 值,以确保位于边界的像素通过距离比较,或者,在渲染阴影纹理时,稍微修正游戏对象的法线。当开启阴影时,这些值可以通过灯光检视视图中的 阴影偏差 Bias阴影法线偏差 Normal Bias 属性设置。

不要将 阴影偏差 Bias 设置的太大,因为阴影周围靠近游戏对象的区域有时会被错误地照亮。从而导致阴影和游戏对象分离,使得游戏对象看起来好像是在地面上空飞行。

A high Bias value makes the shadow appear disconnected from the GameObject

阴影偏差 Bias 过大,使得阴影与游戏对象分离。

同样地,阴影法线偏差 Normal Bias 过大,会使阴影相比游戏对象显得太窄:

A high Normal Bias value makes the shadow shape too narrow

阴影法线偏差 Normal Bias 过大,使得阴影的形状太窄

在某些情况下,阴影法线偏差 Normal Bias 可能导致称为『光线泄漏』的意外效果,光线穿过相邻的几何体,泄漏到被遮盖的区域。一个可行的解决方案是,打开游戏对象的 网格渲染器 Mesh Renderer,修改 Cast Shadows 属性为 Two Sided。但是这个方案可能需要更多的计算资源,增加渲染场景时的性能开销,尽管它在某些情况下确实有效。

为了避免发生这种意外效果,光源的阴影偏差可能需要调整。通常,通过眼睛来判定正确的偏差值更容易些,而不是尝试通过计算获得。

为了进一步防止阴影痤疮,我们使用了一种成为『阴影着陆』的技术(参见 平行光阴影:阴影着陆)。通常,这种技术是有效的,并且可以为非常大的三角形创建人为的视觉效果。

A low Shadow near plane offset value create the appearance of holes in shadows

设置较低的 阴影近剪裁平面偏移 Shadow near plane offset 值,导致阴影中的孔状效果。

调整 阴影近剪裁平面偏移 Shadow Near Plane Offset 属性,可以解决这个问题。该值太大,也会导致阴影痤疮。

Correct shadowing

正确的投影