[自学记录04|百人计划]前向渲染和延迟渲染

一、渲染路径

渲染路径决定光照的实现方式。简言之,就是当前渲染目标使用光照的流程。

二、渲染方式

1.前向渲染(Forward Rendering)

[自学记录04|百人计划]前向渲染和延迟渲染_第1张图片 待渲染几何体→顶点着色器→片元着色器
→渲染目标

在渲染每一帧时,每个顶点/片元都要执行一次片元着色器代码,这时需要将所有的光照信息都传递到片元着色器中。虽然大部分情况下的光源都趋向于小型化,而其照亮的区域也不大,但即便是光源离这个像素所对应的世界空间中的位置很远,但计算光照时,还是会把所有的光源都考虑进去,而这样必然导致许多的浪费。

例如,物体受n个光源影响,那么在每一个片元执行着色器代码时,都必须吧这n个光源都传递进着色器中执行光照计算。

简而言之,前向渲染有以下几个规则:

规则一:最亮的几个光源会被实现为像素光照

规则二:然后最多4个光源会被实现为顶点光照

规则三:剩下的光源会被实现为效率较高的球面调谐光照(Spherical Hamanic),这是一种模拟光照

规则一补充说明

  • 1.最亮的那盏光一定是像素光照
  • 2.Light的Render Mode是important的光一定是像素光照
  • 3.如果前面的两条加起来的像素光照小于Quality Setting里的Pixel Light Count(最大像素光照数量),那么从剩下的光源中找出最亮的那几盏光源,实现为像素光照。
  • 4.最后剩下的光源,按照规则2或3。
  • 5.在base pass里执行一盏像素光、所有的顶点光和球面调谐光照,并且进行阴影计算。
  • 6.其余的像素光每盏一个Additional Pass,并且这些pass里没有阴影计算。
  • 7.场景中看到的阴影,全是base pass里计算出最亮那盏像素光的阴影,其他像素光是不计算阴影的。

[自学记录04|百人计划]前向渲染和延迟渲染_第2张图片Unity的Frame Debug很容易看出前向渲染的过程,正如上述规则描述的一样


2.延迟渲染(Deferred Rendering)

[自学记录04|百人计划]前向渲染和延迟渲染_第3张图片 待渲染几何体→顶点着色器→MRT→光照计算→渲染目标

将渲染过程拆分成两个渲染通路(pass)。

第一个pass称为几何处理通路。首先将场景渲染一次,获取到待渲染对象的各种几何信息存储到名为G-buffer的缓冲区中,这些缓冲区将会在之后用作更复杂的光照计算。由于有深度测试,所以最终写入G-buffer中的各个数据都是离摄像机最近的片元的几何属性,这意味着最后在G-buffer中的片元必定要进行光照计算的。

第二个pass称为光照处理通路。该pass会遍历所有G-buffer中的位置、颜色、法线等参数,执行一次光照计算。

[自学记录04|百人计划]前向渲染和延迟渲染_第4张图片 虚幻中延迟渲染的G-Buffer

G-Buffer

G-Buffer,全称Geometric Buffer ,译作几何缓冲区,它主要用于存储每个像素对应的位置(Position),法线(Normal),漫反射颜色(Diffuse Color)以及其他有用材质参数。根据这些信息,就可以在像空间(二维空间)中对每个像素进行光照处理。


简单的说,延迟渲染实际上可以看作是一个后处理,只不过在后处理之前,它把所有需要的信息都已经拿到了,这些信息都分别存储在一张自己的RT中,而所有RT都存储在G-Buffer中,同时也因为这样,所以延迟渲染对许多后处理的支持非常好。

 左图为Unity中延迟渲染的Frame Debug[自学记录04|百人计划]前向渲染和延迟渲染_第5张图片


三、前向渲染和延迟渲染的比较

1.前向渲染的优点和缺点

(1) 优点

1、支持半透明渲染

2、支持使用多个光照pass

3、支持自定义光照计算方式

(2) 缺点

1、光源数量对计算复杂度影响巨大

2、访问深度等数据需要额外计算

2.延迟渲染的优点和缺点

(1) 优点

1、大量光照场景优势明显

2、只渲染可见像素,节省计算量

3、对后处理支持良好

4、用更少的shader

(2) 缺点

1、对MSAA支持不友好(因为G-Buffer存储的是已经光栅化了的片元,无法细分)

2、透明物体渲染存在问题 (因为G-Buffer保留的都是离相机最近的片元,深度会有问题,渲染透明物体只能使用前向渲染的方式向渲染)

3、占用大量的显存带宽 (存储G-Buffer)

3.延迟渲染的改进—Tile-BasedDeferred Rendering

[自学记录04|百人计划]前向渲染和延迟渲染_第6张图片

Tile-Based Deferred Rendering,简称TBDR,意思是分块延迟渲染,这里指的是SIGGRAPH 2010上提出的,通过分块来降低带宽内存用量,它计算每个分块的深度范围(depth range),求得每个 tile 的 包围盒bounding box。然后,计算每个分块的包围盒bounding box会受到哪些光源影响,把那些光源的索引储存在分块的光源列表里。最后,逐个分块进行着色,对每像素读取 G-buffer 和光源列表及相关的光源信息。因此,G-buffer的数据只会被读取1次且仅1次,写入 color buffer也是1次且仅1次,大幅降低内存带宽用量。不过,这种方法需要计算光源会影响哪些分块,这个计算又称为光源剔除(light culling),可以在 CPU 或 GPU(通常以 compute shader 实现)中进行。用GPU计算的好处是,GPU 计算这类工作比 CPU 更快,也减少 CPU/GPU 数据传输。而且,可以计算每个分块的深度范围(depth range),作更有效的剔除。

对比 Deferred Rendering,之前是对每个光源求取其作用区域 light volume,然后决定其作用的的 pixel,也就是说每个光源要求取一次。而使用 TBDR,只要遍历每个 pixel,让其所属 tile 与光线求交,来计算作用其上的 light,并利用 G-Buffer 进行 Shading。一方面这样做减少 了所需考虑的光源个数,另一方面与传统的 Deferred Rendering 相比,减少了存取的带宽。

(另一个是PowerVR基于手机GPU的TBR架构提出的,通过HSR减少overdraw,见[自学记录03|百人计划]移动端GPU的TB(D)R架构基础__Yhisken的博客-CSDN博客)

四、其他

1.Light Pre-Pass/Deferred Lighting

减少G-buffer占用的过多开销,支持多种光照模型

和延迟渲染的区别:用更少的buffe信息,着色计算的时候用的是forward,所以第三步开始都是前向渲染(可以对不同的物体进行不同的光照模型)

2.Forward+/Tiled Forward Rendering

减少带宽,支持多光源,强制需要一个preZ

通过分块索引的方式,以及深度和法线信息来到需要进行光照计算的片元进行光照计算。需要法线和深度的后处理需要单独渲染一个rt出来。强制使用了一个preZ,进行了一个深度预计算。

在传统前向渲染基础上添加了一个基于计算着色器的光源剔除阶段(light-culling),使得使用前向渲染更多光源变得可能。可以参考这位大佬写的Forward+ Shading - 知乎 (zhihu.com)

3.Clustered Rendering

群组渲染的主要思路也是对光源进行剔除,可以看做是分块渲染的一个升级版。分块渲染的思路是对每一个图块进行光源剔除,而群组渲染的思路则更加简单粗暴,在分块渲染的基础上,在深度方向也进行多次分层。使得带宽相对减少,多光源下效率提升。

更多可以参考:渲染路径(Rendering Path)与常见渲染技术 - 知乎 (zhihu.com)

参考

3400_哔哩哔哩_bilibili

3400延迟渲染 (qq.com)

Real-Time Rendering笔记(6):正向渲染和延迟渲染 - 知乎 (zhihu.com)

渲染路径(Rendering Path)与常见渲染技术 - 知乎 (zhihu.com)

Forward+ Shading - 知乎 (zhihu.com)

你可能感兴趣的:([自学记录],TBR,GPU,性能优化,学习记录,渲染)