![在线客服](/v23/gif/kf-66e64eb5.gif)
URP中的延迟渲染技术是什么
延迟渲染其本质是通过将几何通道与光照通道分离,以比标准多通道前向渲染器更低的成本渲染更多的灯光。目前它已经广泛用于游戏场景的灯光制作中,比如深受海内外玩家青睐的作品《原神》就采用了延迟渲染技术。
作为 Unity 重点推广的渲染管线,URP 在功能上正逐步与内置渲染管线靠近,并在未来会替换掉内置渲染管线。这就需要增添一些内置渲染管线支持,延迟渲染功能就是其中比较重要的一个。
另一方面, URP 旨在为游戏开发人员提供兼容 Unity 所支持的所有平台的渲染管线,所以该管线可在从低端移动设备到高端台式 PC 的平台上运行。将延迟着色添加到 URP 中意味着需要探索各种方法来解决目标平台的差异,这项工作繁重而紧迫。
令人惊喜的是:Unity 在 URP 12.0 以及以上版本中添加了对延迟渲染路径的支持,大家可以在 Unity 2021.2 及以上版本中进行体验这个功能。
Unity中为什么要设置两条渲染路径?
虽然我们能够很简单地在 URP 中切换前向和延迟渲染路径,但是对于刚入门 Unity 的新手来说,如何在前向和延迟渲染路径这两种渲染方法之间进行选择,则需要深刻地理解为什么 Unity 会有多个渲染路径,以及了解两种渲染方法背后的动机。接下来带大家来一起探讨下:
一切都与照明有关。我们总是说灯光很昂贵,主要是因为当物体处于灯光范围内时,必须进行大量计算才能找出像素的有效颜色。在 Unity 中,可以按顶点、按像素或按球谐函数评估灯光。
在逐像素光照中,每个像素的颜色都是单独计算的(如左图)。您可以看到,即使我在此示例中使用低多边形球体,但是光照仍然使它看起来是圆形的效果。如果不是看低多边形的边缘,真的很难发现顶点的位置。
然后是逐顶点光照。它对每个顶点进行一次光照计算。顶点之间的所有其他像素使用常规颜色混合算法评估颜色(无需进一步的光计算)。这是最便宜的照明方法。那么我们如何在 Unity 中打开像素和顶点照明开关,在 Light 组件中 Render Mode(渲染模式)属性选项下(如下图所示)进行选择,其中 Important 选项是强制灯光为像素光,Not Important 是顶点光,Auto 是使最强的光成为像素光。
从画面对比效果来看,游戏开发者更加青睐逐像素光照而不是逐顶点光照(URP 不支持逐顶点光照)。但是逐像素光照有一个明显的缺点,那就是每盏灯光都会导致光照范围内的每个对象增加额外的渲染通道。而可以影响对象的灯光数量是有限的,在最新的 Unity 的版本中我们已经提升了 URP 中的光源限制上限,从每个对象可以受 4 个光源影响增加到了可以受 8 个光源的影响。
延迟渲染过程的刨析
有一种技术可以让您在场景中使用尽可能多的灯光,同时将性能保持在合理的水平。如果场景对象在光照范围内(投射阴影的对象除外),它不会限制阴影的数量,也不会导致额外的绘制通道。它被称之为延迟渲染路径。
延迟渲染为什么会有这样的优点呢?为了更好地理解延迟渲染过程,让我们看一下 Frame Debugger。
我们发现场景渲染从渲染所有几何图形开始,没有应用任何光影信息,如下图所示:
那么显卡如何知道给这张只是渲染了几何图形的平面图像应用光影信息呢?这里就需要感谢深度缓冲区(Depth Buffer)。深度缓冲区存储有关每个像素位于相机距离远近的信息。如下所示:
但是仅靠深度信息不足以确定应如何在表面上应用光,我们至少还需要方向。3D 空间中的方向通常由法线表示。正好,除了颜色缓冲区和深度缓冲区之外,还有一个带法线的缓冲区。
基于该信息,可以渲染灯光和阴影。场景中有多少物体并不重要,因为一切都只在最终图像上完成。最后将光照通道的反转版本(1–color)与第一个不透明图像混合以获得最终结果如下图所示。
综上所述我们了解:延迟渲染之所以具有多灯光、高性能的原因主要是场景中大多数模型是在没有光照计算的情况下渲染的,当场景渲染接近完成时,光照才会应用于渲染的 2D 图像。在这个阶段进行操作就是我们通常称为的在屏幕空间中进行操作。知道了这一点,我们可以说延迟渲染中的光照是屏幕空间进行的。
如何在URP中使用延迟渲染路径与Accurate G-buffer normals 属性?
首先在你的 URP 工程中在 Project Settings>Graphics 下找到 Scriptable Render Pipeline Settings 中的 URP 资产配置文件 URP Asset。
然后找到对应的 URP 渲染器资产 Universal Renderer Data,在 Renderering> Rendering Path。选择 Rendering Path 为 Deferred,这样我们就开启了延迟渲染路径。
值得注意的是选择 Deferred Rendering Path 后,Unity 会显示 Accurate G-buffer normals 属性。
通过 Accurate G-buffer normals 属性,可以配置 Unity 在将法线存储在几何缓冲区(Gbuffer)中时如何对法线进行编码。那么 Accurate G-buffer normals 属性有什么作用呢,我们来看下:
Accurate G-buffer normals 关闭:关闭这个选项可提高性能,尤其是在移动端 GPU 上,但可能会导致光滑表面上出现色带瑕疵。
Accurate G-buffer normals 开启:Unity 使用八面体编码将法线矢量的值存储在法线纹理的 RGB 通道中。通过这种编码,法线矢量的值更加准确,但编码和解码操作会给 GPU 带来额外的负担。对于面向 desktop 和 consoles 平台的开发人员,启用“AccurateG-buffer normals”应该是默认设置。
我们在场景中创建一个球体 Sphere,调节球体的光滑度,我们来观察下打开 Accurate G-buffer normals 属性前后,球体表面效果对比。如下图所示:
URP中两种延迟渲染解决方案与内置管线延迟渲染解决方案性能对比
目前没有一种完美的延迟算法可以完全适配 URP 的多平台性。所以为了适应目标平台的多样化以及不断变化的 GPU 硬件的限制和特殊性,URP 中的延迟渲染算法有两种实现方式。分别是经典的 Stencil-based 延迟渲染算法和目前在台式机 GPU 上比较流行的 Tiled-based 延迟渲染算法(其中基于 Stencil-based 解决方案在所有平台上成熟稳定,基于 Tiled-based 的延迟解决方案目前还在更多平台上进行测试)。
关于这两种算法的具体内容不是我们本教程所讲的重点,我们来看一组实验数据:同场景下基于 URP 的两种延迟解决方案与内置渲染管线下的延迟解决方案在不同平台上的性能对比。
我们创建了一个有着 1 个主 directional light, 64 point lights, 灯光模式为 baked lighting 的测试场景。
在 Nvidia Gfx Geforce 1050 上与 iPhone 8 A11 Bionic 性能对比。
从数据表中我们不难发现首先:URP 中延迟渲染技术性能要优于内置渲染管线,其次,在 URP 中的两种延迟渲染解决方案性能在不同平台上性能各有优势。
延迟渲染管线的限制与下一代多光照渲染技术Forward+
延迟渲染并不是万能的。它还存在一些限制。我们来看下:
首先,延迟渲染不允许我们渲染半透明对象。这是因为如果场景中存在半透明的东西,则无法记录通过半透明对象可见的对象和当前对象本身的深度和法线。Unity 在整个过程结束时使用前向渲染路径处理此限制渲染半透明对象。
其次,缺乏抗锯齿支持。原因类似于半透明对象的问题,您可以使用屏幕空间 SMAA 算法,但效果可能不太好看。
再次, URP 中的相机堆叠 Camera Stack 使用也是有限制的。Unity 使用延迟渲染路径仅渲染 Base Camera,Unity 使用前向渲染路径渲染所有 Overlay Camera,也就是说只允许 Base Camera 相机使用延迟渲染模式。Overlay Camera 叠加相机将恢复到正向渲染模式。
那有没有一种解决方案可以克服前向渲染与延迟渲染的限制还能够有延迟渲染处理多光照的优点。这就是下一代多光照渲染技术Forward+,也称为基于Tile的前向渲染,是结合了前向渲染和基于Tile灯光剔除来减少着色过程中灯光数量的一种渲染技术。这将显著改善URP中的前向渲染器对着色时使用的灯光数量的限制。借助URP中 Forward+的可用性,我们可以在场景中合并比当前前向渲染中每个对象8个灯光的限制更多的灯光。同时,随着灯光和对象数量的增加,我们的项目中的渲染性能将得到更好的扩展。
目前 URP 团队也在紧锣密鼓地实现Forward+技术,到时候我们将能够选择Forward+作为可供选择的渲染器,就如当前的 Forward和Deferred渲染器之间切换一样。
![底部宣传图](/v23/png/bg-ad4f8102.png)