• 【渲染学习随笔】延迟渲染 VS 前向渲染


     最近在学习 UE4 的渲染原理,其中 UE 官网在讲渲染概述时提到 [1]

    延迟着色(Deferred Shading)

    虚幻引擎 4 中所有光照均为延迟光照(Deferred),这点与虚幻引擎 3 的前置光照(Forward)完全不同。材质将它们的属性写入 GBuffers,光照过程则读取材质每个像素的属性,并对他们执行光照处理。

    (注:在这里的延时着色和延时渲染原理相同,但层级不同。可以理解为相同的东西

    首先什么是延时渲染(Deferred Rendering)?延时渲染是将着色(Shading)延迟到深度计算之后进行处理的一种渲染方法 [2],相比于传统的前向渲染(Forward Rendering),延迟渲染在进行光照计算时有显著的优势。具体是为什么,我们需要了解两种不同渲染方法的大致原理:

    • 前向渲染:将光源对场景中的渲染目标(Render target)以及片元等影响逐一计算,然后进行深度测试,一并输送给图形硬件输出渲染结果 [3]。流程图如下:

    图 1:前向渲染流程 [3]
    • 延迟渲染:将场景内所有物体绘制到 G缓冲(G-Buffer,稍后会讲后在进行着色计算,此时着色计算的对象便不是场景中的每一个渲染目标,而是 shuG 缓冲里面的每一个片元信息(可以理解为被先渲染到屏幕上的像素信息),其中包括了该片元对应的位置,法线,漫反射颜色,高光颜色等数据[2,3],最后进行深度测试。流程图如下:

    图 2:延迟渲染流程 [3]

    由此可见,相比于前向渲染中需要将光源与所有的渲染目标计算光照结果,延时渲染只需要将光源数据与该帧被渲染的片元进行计算,而每帧需要渲染的片元是小于甚至远远小于场景中的所有渲染对象的顶点和面的。这对于渲染多光源场景有显著的优势:假设我们的场景有 1000 个光源,且有 1000 个渲染目标,每个渲染目标有 1000 个顶点,渲染屏幕分辨率为(1024 * 768),前向渲染与延时渲染的时间复杂度分别是:

    • 前向渲染:O(# of 光源 * (# of 渲染目标 * # of 顶点))= 1000 * (1000 * 1000) = 109
    • 延时渲染:O(# of 光源 * 屏幕分辨率)= 1000 * 1024 * 768 = 786432000 ≈ 8 * 108

    通过比较不难发现,延时渲染在光源多,渲染目标多且复杂的情况下有着明显的优势。

    下面介绍一下延时渲染的详细过程,其中分成了两个 Pass [2]

    1. 几何处理 PASS:在这个阶段计算渲染目标映射到像素(片元)的信息,其中包括对应到像素的位置,颜色,法线等信息。然后这些信息将会被存到 G 缓存中。G 缓存(Geometric Buffer)主要储存了每个像素对应的信息,包括上面提到的信息外,还包括漫反射(Diffuse)颜色,折射(Specular)颜色等。如下图是一个 G-Buffer 储存的信息:

     图 3:G 缓存中存储的信息 [2]

    2. 光照处理 PASS:因为我们最终绘制到屏幕上的是一个屏幕大小的矩形,我们使用上一步中 G 缓冲中的信息和场景中的每一个光源进行计算。注意这时我们不需要将光与场景中的每一个模型上的每一个片元进行计算,而只需要将光源与 G 缓冲中的每一个像素数据进行计算。

    延迟渲染的过程总览如下图:

    图 4 :延迟渲染过程总览 [2]

    尽管延迟渲染有如此多的优势,但在大部分手机平台的游戏上,前向渲染依然是主流。UE4 的延时渲染也仅仅是支持 PC 端和部分主机端游戏,手机游戏使用的仍是前向渲染 [5]。这是因为延时渲染有一定的局限性:

    1. 首先,应用延时渲染对硬件有一定要求。首先,延时渲染需要硬件能够支持 MRT,因为延迟渲染需要一次产生多个渲染目标 [6]。手机平台的图形硬件并不支持 MRT 所以不能使用延迟渲染。

    2. 延时渲染要求硬件有高带宽。毕竟一个 G 缓冲中需要存储大量信息,手机大多不具有这样带宽的传输。

    3. 延时渲染在没有特殊处理的情况下,无法渲染透明物体,抗锯齿,和进行阴影渲染 [7]。但这些问题很多都已经通过其他方法被解决或改进。由于前两点设计手机硬件的短板导致无法进行延时渲染,这些问题在此不做过多讨论,详见参考资料 [2] 和 [7]。

    补充 [4]:在前文提到了 pass 这个词,但没有做很好的解释,在写的时候自己也不明不白。。所以决定还是补充一下:渲染 pass 涉及多通道渲染技术(multipass rendering techniques),其理念是在一次只渲染一个渲染目标的一部分,在最后合并成最后的结果。每一次对渲染目标进行部分渲染的方式既是一个 pass,每一个 pass 不需要对渲染完整的渲染对象。比如我们上文所讲的延迟渲染:一个 pass 渲染着色前的画面,一个 pass 渲染着色后的画面。


    参考资料:

    [1] Unreal Engine --- Rendering Overview

    [2] 毛星云 ---【《Real-Time Rendering 3rd》 提炼总结】(七) 第七章续 · 延迟渲染(Deferred Rendering)的前生今世

    [3] Brent Owens --- Forward Rendering vs. Deferred Rendering

  • 相关阅读:
    【转】Git: There is no tracking information for the current branch.
    【转】git多个远程仓库
    【转】python批量快速合并excel文件
    【转】HTML5-postMessage实现跨域
    Python3正则表达式search和findall差异讨论
    Python Segmentation fault错误定位办法
    Python3压缩和解压缩实现
    Python3+profile性能分析
    案例:ADG环境遇到redo日志member路径有误以及RMAN-6571错误
    CentOS7的udev的绑定规则
  • 原文地址:https://www.cnblogs.com/thdt/p/13950038.html
Copyright © 2020-2023  润新知