Version: 2020.1
阴影级联
Lighting 窗口

阴影故障排除

阴影性能

实时阴影具有相当高的渲染开销;任何可能投射阴影的游戏对象都必须首先渲染到阴影贴图中,然后该贴图将用于渲染可能接受阴影的对象。

柔和阴影比生硬阴影具有更大的渲染开销,但这仅影响 GPU,不会导致额外的 CPU 工作。

阴影暗斑

直接获得光照的表面有时看起来部分处于阴影中。之所以出现这种情况,是因为应该精确位于阴影贴图中指定距离处的像素有时被计算为更远距离(这是对阴影贴图使用阴影过滤或低分辨率图像的结果)。造成的结果是阴影中出现任意像素图案(这些像素其实应当获得光照),带来称为“阴影暗斑”(shadow acne) 的视觉效果。

阴影暗斑的出现形式是虚假的自我阴影瑕疵
阴影暗斑的出现形式是虚假的自我阴影瑕疵

Bias 属性

为了防止阴影暗斑,可在阴影贴图中的距离上添加 Bias 值,从而确保边线上的像素确实符合比较预期,或者确保在渲染到阴影贴图时游戏对象可以沿着自身法线插入一点点。启用阴影后,这些值由 Light Inspector 窗口中的 BiasNormal Bias 属性设定。

不要将 Bias 值设置得太高,因为游戏对象附近的阴影周围区域有时会被错误地照亮。这会导致阴影脱离游戏对象,使游戏对象看起来好像飘在地面上方。

高 Bias 值使阴影与游戏对象看起来是脱离的
Bias 值使阴影与游戏对象看起来是“脱离”的

同样,将 Normal Bias 值设置得太高会使阴影对于游戏对象来说太窄:

高 Normal Bias 值使阴影形状太窄
Normal Bias 值使阴影形状太窄

在某些情况下,__Normal Bias__ 会导致称为“光渗”(light bleeding) 的不良效果,这种情况下,光线从附近的几何体渗透到应该产生阴影的区域。一种可能的解决方案是打开游戏对象的网格渲染器,并将 Cast Shadows 属性更改为 Two Sided。这种做法有时会有所帮助,但可能会占用更多资源,并在渲染场景时增加性能开销。

光源的 Bias 值可能需要适当调整以免产生不想要的效果。通常用眼睛衡量正确值会更简单,而不是试图计算该值。

矫正阴影
矫正阴影

阴影平坠

为了进一步防止阴影暗斑,我们采用一种称为__阴影平坠__的技术。该技术旨在减少沿光照方向渲染阴影贴图时使用的光照空间范围。这可以提高阴影贴图的精度,减少阴影暗斑。

显示阴影平坠原理的图形
显示阴影平坠原理的图形

在上图中:

  • 浅蓝圆圈代表阴影投射物
  • 深蓝矩形代表原始光照空间
  • 绿线代表优化的近平面(排除了在视锥体中不可见的所有阴影投射物)

将这些阴影投射物钳制在优化空间的近裁剪面(在顶点着色器中)。请注意,虽然这通常很有效,但对于穿过近裁剪面的大型三角形,这会带来瑕疵:

大三角形问题
大三角形问题

在此情况下,只有蓝色三角形的一个顶点位于近裁剪面背后并被钳制到此处。但是,这会改变三角形的形状,并可能产生不正确的阴影。

您可以从 Quality 窗口中调整 Shadow Near Plane Offset 属性以避免发生此问题。这将拉回近裁剪面。但是,如果将此值设置得非常高,最终会引入阴影暗斑,因为它会提高阴影贴图需要在光照方向上覆盖的范围。或者,您也可以细分有问题的阴影投射三角形。

阴影不显示

如果您发现一个或多个对象未投射阴影,则应检查以下几点:

  • 可在 Quality 窗口中彻底禁用实时阴影。确保启用了正确的质量级别并为该设置启用了阴影。

  • 场景中的所有网格渲染器都必须正确设置相应的 Receive ShadowsCast Shadows。默认情况下两者都已启用,但请检查确保未意外禁用它们。

  • 只有不透明对象才投射和接受阴影,因此使用内置透明着色器或粒子着色器的对象既不会投射也不会接受阴影。通常,您可以使用透明镂空着色器代替具有“间隙”的对象,例如栅栏、植被等。自定义着色器必须采用像素光照并使用几何渲染队列

  • 使用__顶点光照 (VertexLit)__ 着色器的对象不能接受阴影,但可投射阴影。

  • 如果游戏对象的材质具有“无光照”类型的着色器,Unity 无法为这些游戏对象计算阴影。只有材质的着色器支持光照时,Unity 才能为材质计算阴影。

  • 在内置渲染管线中,使用前向渲染路径时,有些着色器只允许最亮的方向光投射阴影(这种情况尤其发生在 Unity 4.x 版本的旧版内置着色器中)。如果想使用多个阴影投射光,则应改用延迟着色 (Deferred Shading) 渲染路径。您可以使用 fullforwardshadows 表面着色器指令启用您自己的着色器以支持“全阴影”。

阴影级联
Lighting 窗口