延迟渲染管线介绍
B站视频:图形 3.4 延迟渲染管线介绍
文章目录
- 延迟渲染管线介绍
- 渲染路径
- 前向渲染
- 渲染流程
- 光照规则
- 延迟渲染
- 渲染流程
- 几何缓冲区 G-buffer
- 不同渲染路径的优劣以及特性
- 优劣
- Unity中渲染路径设置
- 移动端优化
- 分块延迟渲染
- 其他渲染路径
- 不同路径下光源shader编写
- 参考资料
渲染路径
渲染路径(Rendering Path),决定光照的实现方式。简言之,就是当前渲染目标使用光照的流程。
- 前向渲染(Forward Rendering)
- 延迟渲染(Defferred Rendering)
前向渲染
发生在渲染管线的顶点处理阶段,会计算所有的顶点的光照。全平台支持。
渲染流程
待渲染几何体 → 顶点着色器 → 片元着色器 → 渲染目标
在渲染每一帧时,每个顶点/片元都要执行一次片元着色器代码,这时需要将所有的光照信息都传递到片元着色器中。虽然大部分情况下的光源都趋向于小型化,而其照亮的区域也不大,但即便是光源离这个像素所对应的世界空间中的位置很远,但计算光照时,还是会把所有的光源都考虑进去。
例如,物体受n个光源影响,那么在每一个片元执行着色器代码时,都必须把这n个光源都传递进着色器中执行光照计算。
光照规则
- 规则一:最亮的几个光源会被实现为像素光照;
- 规则二:然后最多4个光源会被实现为顶点光照;
- 规则三:剩下的光源会被实现为效率较高的球面调谐光照(Spherical Hamanic),这是一种模拟光照。
规则一补充说明:
- 最亮的那盏光一定是像素光照;
- Light的Render Mode是important的光一定是像素光照;
- 如果前面的两条加起来的像素光照小于Quality Setting里的Pixel Light Count(最大像素光照数量),那么从剩下的光源中找出最亮的那几盏光源,实现为像素光照;
- 最后剩下的光源,按照规则二或规则三 ;
- 在base pass里执行一盏像素光、所有的顶点光和球面调谐光照,并且进行阴影计算;
- 其余的像素光每盏一个Additional Pass,并且这些pass里没有阴影计算;
- 场景中看到的阴影,全是base pass里计算出最亮那盏像素光的阴影,其他像素光是不计算阴影的。
延迟渲染
延迟渲染(Deferred Rendering),主要解决大量光照渲染的方案。
延迟渲染的实质,是先不要做迭代三角形做光照计算,而是先找出来能看到的所有像素,再去迭代光照。直接迭代三角形的话,由于大量三角形你是看不到的,无疑是极大的浪费。
渲染流程
待渲染几何体 → 顶点着色器 → MRT → 光照计算 → 渲染目标
将渲染过程拆分成两个渲染通路(pass)。
第一个pass称为几何处理通路。首先将场景渲染一次,获取到待渲染对象的各种几何信息存储到名为G-buffer的缓冲区中,这些缓冲区将会在之后用作更复杂的光照计算。由于有深度测试,所以最终写入G-buffer中的各个数据都是离摄像机最近的片元的几何属性,这意味着最后在G-buffer中的片元必定要进行光照计算的。
第二个pass称为光照处理通路。该pass会遍历所有G-buffer中的位置、颜色、法线等参数,执行一次光照计算。
几何缓冲区 G-buffer
G-Buffer,全称Geometric Buffer ,译作几何缓冲区,它主要用于存储每个像素对应的位置(Position),法线(Normal),漫反射颜色(Diffuse Color)以及其他有用材质参数。根据这些信息,就可以在像空间(二维空间)中对每个像素进行光照处理。
不同渲染路径的优劣以及特性
-
后处理方式不同
假设需要深度信息来进行后处理,前向渲染就需要单独渲染出一张深度图,而延迟渲染就可以直接用G-Buffer里面的深度来进行计算。
-
着色计算不同
由于延迟渲染光照计算统一是在Light Pass中计算的,所以只能算一个光照模型,如果需要用到其他的光照模型,只能切换Pass。
- 抗锯齿方式不同
优劣
渲染方式/优劣 | 优点 | 缺点 |
---|---|---|
前向渲染 | 1. 支持半透明渲染; 2. 支持使用多个光照pass; 3. 支持自定义光照计算方式。 | 1. 光源数量对计算复杂度影响巨大; 2. 访问深度等数据需要额外计算。 |
延迟渲染 | 1. 大量光照场景优势明显; 2. 只渲染可见像素,节省计算量; 3. 对后处理支持良好; 4. 用更少的shader。 | 1. 对MSAA支持不友好; 2. 透明物体渲染存在问题; 3. 占用大量的显存带宽。 |
Unity中渲染路径设置
版本为2022.3.5f1c1。
移动端优化
两个TBDR(分块延迟渲染,Tile-BasedDeferred Rendering)。
- SIGGRAPH 2010上提出的,通过分块来降低带宽内存用量;
- PowerVR基于手机GPU的TBR架构提出的,通过HSR减少overdraw。
分块延迟渲染
作为传统Defferred Rendering的另一种主要改进,分块延迟渲染(Tile-Based Deferred Rendering,TBDR)旨在合理分摊开销(amortize overhead),自SIGGRAPH 2010上提出以来逐渐为业界所了解。
我们知道,延迟渲染的瓶颈在于读写 G-buffer,在大量光源下,具体瓶颈将位于每个光源对G-buffer的读取及与颜色缓冲区混合。这里的问题是,每个光源,即使它们的影响范围在屏幕空间上有重叠,因为每个光源是在不同的绘制中进行,所以会重复读取G-buffer中相同位置的数据,计算后以相加混合方式写入颜色缓冲。光源越多,内存带宽用量越大。
而分块延迟渲染的主要思想则是把屏幕分拆成一个个小的分块,例如每 32 × 32 像素作为一个分块(tile)。计算每个分块的深度范围(depth range),求得每个 分块的包围盒(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 相比,减少了存取的带宽。
其他渲染路径
-
延迟光照 (Light Pre-Pass / Deferred Lighting)
减少G-buffer占用的过多开销,支持多种光照模型。
-
Forward+(Tiled Forward Rendering,分块正向渲染)
减少带宽,支持多光源,强制需要一个preZ。
-
群组渲染(Clustered Rendering)
带宽相对减少,多光源下效率提升。
具体请参考游戏引擎中的光照算法 - 知乎
不同路径下光源shader编写
参考资料
Real-Time Rendering笔记(6):正向渲染和延迟渲染 - 知乎