URP 中的延迟渲染路径
URP 通用渲染器支持两种渲染路径:前向和延迟。
有关渲染路径之间差异的信息,请参阅渲染路径比较一节。
本节将介绍延迟渲染路径。
使用延迟渲染路径渲染的场景示例。
本节包含以下主题:
如何选择延迟渲染路径
要选择渲染路径,请使用 URP 通用渲染器资源中的属性 Lighting > Rendering Path。
选择 Deferred Rendering Path 时,Unity 会显示 Accurate G-buffer normals 属性。
通过 Accurate G-buffer normals 属性,可以配置 Unity 在将法线存储在几何缓冲区(G 缓冲区)中时如何对法线进行编码。
Accurate G-buffer normals 关闭:此选项可提高性能,尤其是在移动端 GPU 上,但可能会导致光滑表面上出现色带瑕疵。
Accurate G-buffer normals 开启:Unity 使用八面体编码将法线矢量的值存储在法线纹理的 RGB 通道中。通过这种编码,法线矢量的值更加准确,但编码和解码操作会给 GPU 带来额外的负担。
有关此设置的更多信息,请参阅 G 缓冲区中的法线编码一节。
Unity Player 系统要求
除 Unity Player 的一般系统要求外,延迟渲染路径还具有以下要求和限制。
最低 Shader Model 版本:Shader Model 4.5。
延迟渲染路径不支持基于 OpenGL 的图形 API:Desktop OpenGL、OpenGL ES 2.0、OpenGL ES 3.0、WebGL 1.0、WebGL 2.0。
实现详细信息
本节将介绍此功能的实现详细信息,以及有关此功能如何工作的技术细节。
G 缓冲区布局
本节将介绍 Unity 如何将材质特性存储在延迟渲染路径中的 G 缓冲区中。
下图显示了 Unity 在延迟渲染路径中使用的渲染目标的每个像素的数据结构。
该数据结构包含以下组件。
Albedo (sRGB)
此字段包含 sRGB 格式的反照率颜色(24 位)。
MaterialFlags
此字段是包含材质标志的位字段:
位 1 - ReceiveShadowsOff:如果设置此位,像素不会接收动态阴影。
位 2 - SpecularHighlightsOff:如果设置此位,像素不会接收镜面高光。
位 4 - SubtractiveMixedLighting:如果设置此位,像素将使用减法混合光照。
位 8 - SpecularSetup:如果设置此位,材质将使用镜面反射工作流程。
如需了解更多技术细节,请参阅 /ShaderLibrary/UnityGBuffer.hlsl
文件。
Specular
此字段包含以下值:
SimpleLit Material:以 24 位存储的 RGB 镜面反射颜色。
Lit Material with metallic workflow:以 8 位存储反射率,不使用 16 位。
Lit Material with specular workflow:以 24 位存储的 RGB 镜面反射颜色。
Occlusion
此字段包含来自烘焙光照的烘焙遮挡值。对于实时光照,Unity 通过将烘焙遮挡值与 SSAO 值结合来计算环境光遮挡值。
Normal
此字段包含以 24 位编码的世界空间法线。有关法线编码的信息,请参阅 G 缓冲区中的法线编码一节。
Smoothness
此字段存储 SimpleLit 和 Lit 材质的平滑度值。
Emissive/GI/Lighting
此渲染目标包含材质发光输出和烘焙光照。Unity 在 G 缓冲区通道期间填充这一字段。在延迟着色通道期间,Unity 将光照结果存储在此渲染目标中。
渲染目标格式:
B10G11R11_UFloatPack32,除非以下条件之一成立:
在 URP 资源中,已开启 Quality > HDR 设置,并且目标 Player 平台不支持 HDR。
在 Player Settings 中,PreserveFramebufferAlpha 设置为 true。
R16G6B16A16_SFloat(如果 Unity 由于项目设置而无法使用 B10G11R11_UFloatPack32)。
如果 Unity 无法使用列表中的其他格式之一,它将使用以下方法的返回结果:
SystemInfo.GetGraphicsFormat(DefaultFormat.HDR)
。
ShadowMask
当 Lighting Mode 设置为 Subtractive 或 Shadow mask 时,Unity 会将此渲染目标添加到 G 缓冲区布局。
Subtractive 和 Shadow mask 模式针对前向渲染路径进行了优化,但在延迟渲染路径中的效率较低。在延迟渲染路径中,应避免使用这些模式,而是使用 Baked Indirect 模式来提高 GPU 性能。
Rendering Layer Mask
当光源层 (Light Layers) 功能已启用(在 URP 资源中选择 Advanced > Light Layers)时,Unity 会将此渲染目标添加到 G 缓冲区布局。光源层功能可能会对 GPU 性能产生重大影响。有关更多信息,请参阅光源层。
Depth as Color
在支持的平台上启用原生渲染通道 (Native Render Pass) 时,Unity 会将此渲染目标添加到 G 缓冲区布局。Unity 会将深度作为颜色渲染到此渲染目标中。此渲染目标具有以下用途:
在 Vulkan 设备上提高性能。
让 Unity 在 Metal API 上获取深度缓冲区,这不允许在同一渲染通道内从 DepthStencil 缓冲区获取深度。
Depth as Color 渲染目标的格式是 GraphicsFormat.R32_SFloat
。
DepthStencil
Unity 保留此渲染目标的四个最高位来标记材质类型。另请参阅 URP Pass 标签:UniversalMaterialType。
对于此渲染目标,Unity 根据平台选择 D32F_S8
格式或 D24S8
格式。
G 缓冲区中的法线编码
在延迟渲染路径中,Unity 将法线存储在 G 缓冲区中。Unity 将每个法线编码为 24 位值。
在 URP 通用渲染器资源的 Rendering Path 属性中选择 Deferred 选项时,Unity 会显示 Accurate G-buffer normals 属性。
通过 Accurate G-buffer normals 属性可以配置 Unity 如何编码法线。
Accurate G-buffer normals 关闭:Unity 将法线矢量的值存储在法线纹理的 RGB 通道中的 G 缓冲区中,每个值 (x, y, z) 为 8 位。这些值经过量化并因此损失一定的精度。此选项可提高性能,尤其是在移动端 GPU 上,但可能会导致光滑表面上出现色带瑕疵。
Accurate G-buffer normals 开启:Unity 使用八面体编码将法线矢量的值存储在法线纹理的 RGB 通道中。通过这种编码,法线矢量的值更加准确,但编码和解码操作会给 GPU 带来额外的负担。
编码的法线矢量的精度类似于前向渲染路径中的采样值的精度。
下图显示了当摄像机非常靠近游戏对象时两个选项之间的视觉差异:
性能注意事项
启用 Accurate G-buffer normals 选项后,由于编码和解码操作,GPU 上会有额外的负担。此负担对于桌面平台和游戏主机来说微不足道,但对于移动端 GPU 来说可能是相当大的。
启用该选项不会增加内存占用。为了存储法线,Unity 在法线纹理中使用相同的 RGB 通道(不管编码如何)。
延迟渲染路径渲染通道
下表显示了延迟渲染路径中的渲染通道事件顺序。
渲染通道事件 | 延迟渲染路径通道 | SSAO 渲染器功能通道 |
---|---|---|
BeforeRendering | ||
BeforeRenderingShadows | ||
AfterRenderingShadows | ||
BeforeRenderingPrePasses | 深度或深度和法线预通道(“仅前向”材质) | |
AfterRenderingPrePasses | ||
BeforeRenderingGbuffer | G 缓冲区通道 (GBufferPass) | |
复制 G 缓冲区深度纹理 | ||
AfterRenderingGbuffer | SSAO(可选) | |
BeforeRenderingDeferredLights | ||
延迟渲染(模板) | ||
AfterRenderingDeferredLights | ||
BeforeRenderingOpaques | 不透明仅前向材质 | |
AfterRenderingOpaques | SSAO 和混合(可选) | |
BeforeRenderingSkybox | ||
AfterRenderingSkybox | ||
BeforeRenderingTransparents | ||
AfterRenderingTransparents | ||
BeforeRenderingPostProcessing | ||
AfterRenderingPostProcessing | ||
AfterRendering |
以下几节将介绍延迟渲染路径渲染通道。
深度或深度和法线预通道
在延迟渲染路径的深度预通道或深度和法线预通道中,Unity 只渲染不支持延迟渲染模型的材质。例如,使用复杂光照着色器的材质就是这样的材质。
在延迟渲染路径中,Unity 不使用深度预通道来生成深度缓冲区的副本(此行为在前向渲染路径中有所不同)。
如果通用渲染器具有 SSAO 渲染器功能,则 Unity 会执行深度和法线预通道。SSAO 使用屏幕空间深度和法线缓冲区来计算环境光遮挡。
可选通道:SSAO 通道、SSAO 与混合通道
如果通用渲染器具有 SSAO 渲染器功能,并禁用 After Opaque 选项(该选项默认禁用),则 Unity 会在 AfterRenderingGbuffer 事件中执行 SSAO 通道。SSAO 渲染器功能会计算 SSAO 纹理。Unity 在延迟渲染通道和渲染“仅前向”材质的通道中对该纹理进行采样。
使用此通道顺序,Unity 可以将烘焙遮挡与 SSAO 渲染器功能的实时遮挡结合起来,并避免烘焙和实时环境光遮挡造成的加倍变暗。
启用 After Opaque 选项后,Unity 在渲染“仅前向”材质后,在 AfterRenderingOpaques 事件中执行 SSAO 和混合通道。然后,Unity 执行额外的全屏通道以将 SSAO 纹理叠加到发光/GI/光照缓冲区上。这会导致接收烘焙遮挡和实时遮挡的区域过度变暗。
性能注意事项
在具有 TBDR 架构的移动平台上,禁用 After Opaque 选项后,Unity 需要额外的渲染目标来进行加载和存储操作。这对性能有重大影响。
在移动平台上启用 After Opaque 选项可提高 GPU 性能。在具有 TBDR 架构的移动平台上,启用此选项可避免额外的渲染目标加载和存储操作。
“仅前向”通道
某些 Unity 着色器使用 Unity 无法在延迟渲染路径中渲染的光照模型。
此类着色器的示例包括:
复杂光照着色器:此着色器的光照模型(例如,透明涂层效果)太复杂,额外的材质属性无法放入 G 缓冲区。
烘焙光照和无光照着色器:这些着色器不计算实时光照,这就是为什么 Unity 在“仅前向”通道期间将它们直接渲染到发光/GI/光照缓冲区中的原因。这种做法比在延迟渲染(模板)通道中评估着色器要快。
自定义着色器:Unity 会渲染未将延迟渲染路径所需的 Pass 标签声明为“仅前向”的着色器。所需的 Pass 标签为
LightMode
和UniversalMaterialType
。有关更多信息,请参阅 URP Pass 标签。
Unity 在前向渲染路径中使用此类着色器来渲染材质。为了使 SSAO 渲染器功能能够使用复杂光照着色器计算材质的环境光遮挡,Unity 必须首先在深度和法线预通道中渲染此类材质。这是因为 Unity 不会在 G 缓冲区通道 (GBufferPass) 中渲染这些材质。有关更多信息,请参阅 URP Pass 标签。
一般实现说明
为了实现最大的平台兼容性,URP 延迟渲染路径使用光源模板体积技术来渲染光源体积并应用延迟着色。
相关代码文件
本节列出的文件包含与延迟渲染路径相关的代码。
负责处理延迟渲染路径的主类:
com.unity.render-pipelines.universal\Runtime\DeferredLights.cs
G 缓冲区通道的 ScriptableRenderPass:
com.unity.render-pipelines.universal\Runtime\Passes\GBufferPass.cs
延迟着色通道的 ScriptableRenderPass:
com.unity.render-pipelines.universal\Runtime\Passes\DeferredPass.cs
用于延迟着色的着色器资源:
com.unity.render-pipelines.universal\Shaders\Utils\StencilDeferred.shader
延迟着色的实用函数:
com.unity.render-pipelines.universal\Shaders\Utils\Deferred.hlsl
用于存储以及从 G 缓冲区加载材质属性的实用函数:
com.unity.render-pipelines.universal\Shaders\Utils\UnityGBuffer.hlsl
ShaderLab Pass 标签
要使 Unity 能够在延迟渲染路径中渲染某个着色器,该着色器必须具有包含以下标签定义的通道:
"LightMode" = "UniversalGBuffer"
Unity 在 G 缓冲区通道期间执行具有此类 LightMode
标签的着色器。
要指示 Unity 必须在延迟渲染路径中的“仅前向”通道中渲染某个材质,请将以下标签添加到着色器通道:
"LightMode" = "UniversalForwardOnly"
"LightMode" = "DepthNormalsOnly"
要指定着色器光照模型(Lit、SimpleLit),请使用 UniversalMaterialType
标签。
有关更多信息,请参阅 URP Pass 标签:LightMode 一节。
限制和性能
本节将介绍延迟渲染路径的限制。
地形混合
当混合四个以上的地形层时,延迟渲染路径生成的结果与前向渲染路径略有不同。发生这种情况的原因是,在前向渲染路径中,Unity 使用多通道渲染方法将前四层与接下来四层分开处理。
在前向渲染路径中,Unity 会合并材质属性,同时为四层的组合属性计算光照。然后,Unity 以相同的方式处理接下来的四层,并对光照结果进行 Alpha 混合。
在延迟渲染路径中,Unity 以一次四层的方式在 G 缓冲区通道中合并地形层,然后在延迟渲染通道期间只计算一次光照。与前向渲染路径的这种差异导致视觉上不同的结果。
Unity 使用硬件混合来组合 G 缓冲区中的材质属性(一次四层),这限制了属性值组合的正确性。例如,不能单独使用 Alpha 混合方程来正确组合像素法线,因为一个地形层可能包含粗糙的地形细节,而另一层可能包含精细的细节。法线的平均或求和算法会导致精度损失。
注意:启用 Accurate G-buffer normals 设置会破坏地形混合。启用此设置后,Unity 使用八面体编码对法线进行编码。由于编码的按位性质(2 x 12 位),不同层中以这种方式编码的法线不能混合在一起。如果您的应用程序需要四个以上的地形层,请关闭 Accurate G-buffer normals 设置。
使用前向渲染路径渲染的地形层
使用延迟渲染路径渲染的地形层
烘焙全局光照和光照模式
启用烘焙全局光照 (Baked Global Illumination) 后,Subtractive 和 Shadowmask 光照模式会给延迟渲染路径中的 GPU 带来额外负担。
出于兼容性原因,延迟渲染路径支持 Subtractive 和 Shadowmask 光照模式,但是,与前向渲染路径的情况不同,这些模式不能提供任何性能改进。在延迟渲染路径中,Unity 使用相同的光照算法处理所有网格,并将 Subtractive 和 Shadowmask 模式所需的额外光照属性存储在 ShadowMask 渲染目标中。
在延迟渲染路径中,Baked Indirect 光照模式提供更好的性能,因为它不需要 ShadowMask 渲染目标。
光源层
URP 实现了光源层功能,可让您配置场景中的哪些光源会影响特定网格。分配给特定光源层的光源只会影响分配给该同一光源层的网格。
要启用光源层功能:在 URP 资源中,选择 Advanced > Light Layers。
性能影响
光源层功能需要一个额外的 G 缓冲区渲染目标来存储渲染层遮罩(32 位)。额外的渲染目标可能会对 GPU 性能产生负面影响。
实现说明
在前向渲染路径中,层功能可指示 Unity 使用一组特定的光源渲染特定的网格。层功能使用剔除遮罩系统。
延迟渲染路径不能使用带有光源剔除遮罩的层系统,因为着色被延迟到渲染循环中的后期阶段(请参阅延迟渲染路径渲染通道表中的延迟渲染(模板)步骤。)