高清渲染管线 (High Definition Render Pipeline) 中的阴影
高清渲染管线的光源可以将阴影从一个游戏对象投射到另一个游戏对象上。这些阴影可以凸显游戏对象的位置和比例,因此能够为场景添加一定程度的深度和真实感,否则看起来会显得扁平。
阴影贴图分辨率
光源的阴影贴图的分辨率决定了其阴影贴图的大小。阴影贴图越大,阴影就越精确,高清渲染管线 (HDRP) 捕获阴影投射几何体中的小细节的能力也越强。以更高分辨率渲染阴影贴图会使其看起来更清晰。
可以在光源组件的 Shadows 部分中设置特定光源的阴影贴图分辨率。
HDRP 为每个光源渲染的阴影贴图数量取决于光源的类型 (Type):
- 聚光灯渲染一个阴影贴图。
- 点光源渲染六个阴影贴图(立方体贴图中的面数)。
- 方向光为每个级联渲染一个阴影贴图。可以从场景体积 (Volume) 的高清阴影设置 (HD Shadow Settings) 中设置方向光的级联数。默认值为四个级联。
HDRP 可动态调整阴影贴图的比例以最大限度提高阴影图集的空间使用率,还可以减少占据屏幕一小部分区域的光源对性能的影响。为此,HDRP 会根据光源覆盖的屏幕区域大小来降低光源的阴影贴图分辨率。屏幕上的这一区域越小,HDRP 根据 Light 组件上设置的值将分辨率缩小得越多。要启用此功能,请找到 Unity 项目的 HDRP 资源的“Shadow”部分,并为需要 HDRP 动态调整阴影贴图的阴影图集启用 Dynamic Rescale 属性。 请注意,HDRP 不支持动态调整缓存的阴影贴图的比例。
阴影图集
HDRP 使用一个阴影贴图图集为所有精准光源阴影渲染一个帧的所有实时阴影,并为方向光阴影渲染另一个阴影贴图图集。
可以在 Unity 项目的 HDRP 资源中设置这些图集的大小。图集大小决定了场景中阴影的最大分辨率。
例如,图集的默认大小为 4096 x 4096,可以容纳:
- 16 个 1024 x 1024 像素的阴影贴图。
- 2 个 2048 x 2048 的阴影贴图 + 4 个 1024 x 1024 的阴影贴图 + 8 个 512 x 512 的阴影贴图 + 32 个 256 x 256 的阴影贴图。
控制屏幕上的最大阴影数量
除了图集,还可以设置 HDRP 在单个帧中能够渲染的最大阴影贴图数。要执行此操作,请打开 Unity 项目的 HDRP 资源,导航到 Shadows 部分,然后输入 Max Shadows on Screen 的值。如果屏幕上的阴影贴图数量高于此上限,则 HDRP 不会渲染它们。
阴影偏差 (Shadow Bias)
阴影贴图本质上是从光源视角投射的纹理。HDRP 在投影中使用偏差使阴影投射几何体不会产生自我阴影。
在 HDRP 中,每个单独的光源组件使用以下参数控制其自身的阴影偏差:
- Near Plane
- Slope-Scale Depth Bias
- Normal Bias
在 Shadows 部分下可以找到这些设置。如果缺少某些属性字段,请单击更多选项齿轮图标来显示它们。有关每个属性如何控制阴影偏差的详细信息,请参阅光源文档。
使用较高的阴影偏差值可能会导致光线通过网格“泄漏”。此问题出现在阴影与其投射物之间存在明显差距的位置,导致阴影形状无法精确表示其投射物。
阴影过滤
HDRP 捕获阴影贴图后,会对贴图进行过滤处理,从而减轻低分辨率阴影贴图上出现的锯齿效果。不同的过滤器会影响阴影的感知清晰度。
要更改所使用的阴影过滤器质量,请更改 Unity 项目的 HDRP 资源中的 Filtering Quality 属性。更高的质量会影响 GPU 性能。 目前有三种用于方向光和精准光源的过滤质量预设。如需了解有哪些可用的过滤质量,请参阅过滤质量表。
阴影遮罩 (Shadowmasks)
HDRP 支持两种混合光照模式:
启用阴影遮罩
要在 HDRP 中使用阴影遮罩,必须在 Unity 项目的 HDRP 资源中启用阴影遮罩支持,然后让摄像机在其帧设置 (Frame Settings) 中使用阴影遮罩:
- 在 Render Pipeline Supported Features 下,启用 Shadowmask 复选框。这样就能在 Unity 项目中启用阴影遮罩支持。
- 接下来,必须使摄像机使用阴影遮罩。在 HDRP 资源中,导航到 Default Frame Settings > Lighting,然后启用 Shadowmask 复选框,使摄像机默认使用阴影遮罩。
HDRP 中的特定设置
为了实现灵活的关照设置,HDRP 允许选择阴影遮罩针对每个光源的行为方式。可以通过更改光源的 Shadowmask Mode 来更改阴影遮罩的行为。将光源的 Mode 设置为 Mixed 即可在 Shadow 部分的 Shadow Map 下拉选单中显示 Shadowmask Mode。
Shadowmask Mode | 描述 |
---|---|
Distance Shadowmask | 当摄像机和光源之间的距离小于精准光源的 Fade Distance 时,使光源为所有游戏对象投射实时阴影。请参阅下文,了解方向光使用的替代距离属性。当光源和摄像机之间的距离大于 Fade Distance 时,HDRP 停止计算光源的实时阴影。此时将对静态游戏对象使用阴影遮罩,而非静态游戏对象不投射阴影。 |
Shadowmask | 使光源仅对非静态游戏对象投射实时阴影。当摄像机和光源之间的距离小于 Fade Distance 时,随后会为静态游戏对象将这些阴影与阴影遮罩合并起来。当光源和摄像机之间的距离大于 Fade Distance 时,HDRP 停止计算光源的实时阴影。此时将对静态游戏对象使用阴影遮罩,而非静态游戏对象不投射阴影。 |
方向光不使用 Fade Distance,而是使用位于场景体积的高清阴影设置 (HD Shadow Settings) 中的 Max Distance 属性。
Distance Shadowmask 更耗费 GPU 资源,但视觉效果更逼真,因为更靠近光源的实时光照比选用低分辨率来表示更远区域的阴影遮罩纹理更精确。
Shadowmask 更耗内存,这是因为摄像机使用阴影遮罩纹理来渲染靠近摄像机的静态游戏对象,从而需要更大分辨率的阴影遮罩纹理。
阴影更新模式 (Shadow Update Mode)
可以使用 Update Mode 来指定 HDRP 用于更新光源的阴影贴图的计算方法。可用的 Update Mode 值如下:
Update Mode | 描述 |
---|---|
Every Frame | HDRP 每帧都更新光源的阴影贴图。 |
On Enable | HDRP 在您每次启用游戏对象时更新光源的阴影贴图。 |
On Demand | HDRP 在您每次提出相应请求时更新光源的阴影贴图。为此,请在光源的 HDAdditionalLightData 组件中调用 RequestShadowMapRendering() 方法。 |
高清渲染管线 (HDRP) 使用阴影缓存,通过仅在必要时才更新光源的阴影贴图来提高性能。HDRP 具有用于精准光源、面光源和方向光的阴影图集,以及专门用于缓存精准光源和缓存面光源的单独阴影图集。缓存方向光使用与普通方向光相同的图集。 光源的 Update Mode 确定 HDRP 是否缓存其阴影贴图:如果将光源的 Update Mode 设置为 OnEnable 或 OnDemand,HDRP 将缓存此光源的阴影贴图。如果将光源的 Update Mode 设置为 Every Frame,HDRP 不会缓存此光源的阴影贴图。 缓存阴影的光源第一次渲染阴影贴图时,HDRP 将其注册到缓存阴影管理器中,然后由该管理器将阴影贴图分配给缓存阴影图集。对于方向光,HDRP 将同一阴影图集用于缓存方向光和非缓存方向光。
如果光源的 Update Mode 设置为 OnDemand,可以手动请求 HDRP 更新光源的阴影贴图。为此,可以访问光源的 HDAdditionalLightData 组件并调用 RequestShadowMapRendering
函数。另外,如果光源具有多个阴影(例如,方向光的多个级联),则可以请求更新特定的子阴影。为此,可以使用 RequestSubShadowMapRendering(shadowIndex)
函数。
对于会缓存阴影的光源,如果将其禁用或将其 Update Mode 设置为 Every Frame,则可以要求 HDRP 将光源的阴影贴图位置保留在缓存阴影图集内。这意味着,如果再次启用光源,HDRP 无需重新渲染阴影贴图,也无需将其放入阴影图集。如需了解如何使光源将其阴影贴图位置保留在缓存阴影图集内,请参阅保留阴影图集位置。
作为常见情况的快捷处理方法,HDRP 提供了一个选项,可在光源的位置或旋转超过某个阈值时自动触发更新。要启用此选项,请选择光源,然后在其 Inspector 的 Shadow 部分中启用 Update on light movement。
可以自定义一个阈值,让 HDRP 根据此阈值确定光源需要移动或旋转多少才触发更新。为此,请使用光源的 HDAdditionalLightData 组件上的 cachedShadowTranslationUpdateThreshold
和 cachedShadowAngleUpdateThreshold
属性。请注意,点光源在确定是否需要在此模式下执行更新时会忽略角度差异。
自定义阴影缓存
HDRP 将精准光源的阴影贴图缓存到一个图集中,将面光源的阴影贴图缓存到另一个图集,并将方向光与非缓存方向光的阴影贴图缓存到相同的图集中。可以彼此独立地更改前两个缓存阴影图集的分辨率。为此需要执行以下操作:
- 选择一个 HDRP 资源,从而在 Inspector 中查看此资源。
- 对于精准光源,请选择 Lighting > Shadows > Punctual Light Shadows。对于面光源,请选择 Lighting > Shadows > Area Light Shadows。
- 将 Cached Shadow Atlas Resolution 的值设置为所需的值。为了方便保持阴影图集的有序结构,请尝试将单个阴影贴图的分辨率保持为 64 的倍数。为了实现最佳组织结构,请针对尽可能多的阴影贴图设置相同的分辨率。
如果在光源请求聚光时阴影图集已满,则缓存阴影管理器不会添加光源的阴影贴图,因此光源不会投射阴影。这意味着管理可用空间是非常重要的工作。可以使用 HDCachedShadowManager.instance.WouldFitInAtlas
helper 函数来检查光源是否适合阴影图集。为了查看光源是否已经在图集内留有位置,或者是否正在等待位置,Render Pipeline Debug 窗口提供了一个选项来记录缓存阴影图集的状态。要使用此选项,请执行以下操作:
- 单击菜单:Window > Render Pipeline > Render Pipeline Debug。
- 选择 Lighting > Shadows。
- 单击 Log Cached Shadow Atlas Status 按钮。这会在 Console 窗口中打印一条消息,指出光源在图集内留有位置还是正在等待位置。
场景加载所有已放置的光源后,如果向场景添加具有缓存阴影的新光源,HDRP 会尝试放置这个光源,以便填充图集内的空缺。但是,根据插入顺序的不同,图集可能会碎片化,可用的空缺不足以放置光源的阴影贴图。在此情况下,可以对图集进行碎片整理以允许添加额外光源。为此,请将目标图集传递给以下函数:HDCachedShadowManager.instance.DefragAtlas
请注意,这会导致 HDRP 将图集中的所有阴影贴图标记为“脏”状态,这意味着在父级光源变为可见状态时 HDRP 会渲染这些贴图。
保留阴影图集位置
如果禁用光源或者将其 Update Mode 更改为 Every Frame,则缓存阴影管理器在缓存阴影图集中不会保留光源阴影贴图的空间,并且 HDRP 会开始在每一帧将光源的阴影贴图渲染为正常阴影图集。如果缓存阴影管理器需要在图集上为另一光源分配空间,它可以覆盖原始光源的阴影贴图当前占用的空间。
如果打算只是暂时将光源的 Update Mode 设置为 Every Frame 且希望稍后将其恢复设置为 On Enable 或 On Demand,可以在图集中保留光源的阴影贴图位置。例如,如果希望 HDRP 缓存远处光源的阴影贴图,但在光源靠近摄像机时在每一帧都对其进行更新,那么在这种情况下就很适合使用此功能。为此,请访问光源的 HDAdditionalLightData 组件并启用 preserveCachedShadow 属性。如果此属性设置为 true
,则 HDRP 会在阴影图集中保留光源的阴影贴图空间。请注意,即使已启用此属性,如果销毁了光源,那么也会丢失其在阴影图集中的位置。
注意事项
在 Unity 编辑器中时,只要修改投射阴影的光源,HDRP 就会更新阴影贴图。在内置应用程序中,更改光源的不同属性或调用以下函数之一时,HDRP 会刷新缓存的阴影贴图:
- SetShadowResolution()
- SetShadowResolutionLevel()
- SetShadowResolutionOverride()
- SetShadowUpdateMode() 或 shadowUpdateMode。在此情况下,仅当模式在“每帧”与“非每帧”之间切换时,HDRP 才会刷新缓存的阴影贴图。
请注意,取决于视图的任何因素都可能会导致缓存阴影贴图出现问题,因为 HDRP 不会在主视图移动时自动更新阴影贴图。在这方面,曲面细分是一个不明显示例。由于曲面细分因子取决于视图,因此主摄像机看到的几何体可能与 HDRP 渲染到缓存阴影贴图中的几何体不匹配。如果明显发生这种情况,应触发一个请求以让 HDRP 更新光源的阴影贴图。为此,请确保光源的 Update Mode 设置为 On Demand,并调用 RequestShadowMapRendering
。
接触阴影 (Contact Shadows)
接触阴影是 HDRP 光线在深度缓冲区内的屏幕空间中行进的阴影,位于近距离范围内。它们可以提供几何体的细小阴影,而这是阴影贴图通常无法捕获的。
有关如何启用和自定义接触阴影的详细信息,请参阅接触阴影 (Contact Shadows) 覆盖文档。
一次只能有一个光源可以投射接触阴影。这意味着,如果有多个光源可以投射在屏幕上可见的接触阴影,则只有占据主导优势的光源会渲染接触阴影。HDRP 根据光源包围盒的屏幕空间大小来选择占主导优势的光源。投射接触阴影的方向光始终为占主导优势的光源。