2021 年 12 月 15 日
About Render Path
目录
- Forward Shading
- 优化Overdraw – Early Z
- 优化Overdraw – Pre Z
- Deferred Shading
- Deferred Lighting
- Tile Based Shading
- Tile Based Deferred Shading
- Forward+
- Cluster Based Shading
- 对比
- 高效的渲染算法要点总结
Forward Shading
- 伪代码
foreach object in scene
foreach light in scene
do shading(object, light)
- 优点
- 算法好理解
- 支持MSAA
- 支持半透明物体
- 缺点
- 算法复杂度高 O(m*n)
- Overdraw显著
- 适用场景
- 光源不多;场景简单的场景
优化Overdraw – Early Z
- 对于不透明物体提早深度测试,来减少PS阶段消耗。
- 但是对于一个大物体和很多小物体的情况会排序失败;并且可能因为开启了AlphaTest等原因打断Early Z。
优化Overdraw – Pre Z
- 伪代码
// Pass 1
foreach object in scene
if object.z < depthBuffer.z
do depthOnly(object)
// Pass 2
foreach object in scene
if object.z == depthBuffer.z
foreach light in scene
do shading(object, light)
- 缺点
- DrawCall增加
- VS计算开销增加
Deferred Shading (光照计算与物体解耦
- 伪代码
foreach object in scene
if object.z < depthBuffer.z
do writeGBuffer(object)
foreach pixel in screen
do readGBuffer(pixel)
foreach light in scene
do shading(pixelGBuffer, light)
- 优点
- 支持更多灯光
- 没有Overdraw
- 光照计算与物体解耦,算法复杂度低 O(m+n)
- 对各种屏幕空间算法友好(各种后处理
- 缺点
- 带宽高
- 无法处理半透明物体
- 无法支持很多材质
- 适用场景
- 光源数量多
- 场景简单
- 材质较为单一
Deferred Lighting
Tile Based Shading (基于tile优化灯光裁剪
- 伪代码
// method 1 - screen space
foreach tile in screen
foreach light in scene
if light in this tile
tile += light
// method 2 - frustum space
foreach tile in screen
get boundingbox for this tile in frustum
calculate zmin and zmax
foreach light in scene
if light.z in zmin and zmax
tile += light
do shading(tiles)
- 如何确定tile的大小?
- 与GPU中的线程组中的线程数大小相关
- 应该是64的倍数
- 不超过1024(DX11上的数,不同的硬件数据不同
- 优点
- 支持的光源数量多
- 可扩展性强
- 缺点
- 深度不连续
- 光源剔除不精确
Tile Based Deferred Shading (Tile Based Shading + Deferred Shading
- 伪代码
// writeGBuffer
foreach object in scene
if object.z < depthBuffer.z
do writeGBuffer(object)
// light culing
// method 1 - screen space
foreach tile in screen
foreach light in scene
if light in this tile
tile += light
foreach tile in screen
foreach pixel in tile
do readGBuffer(pixel)
foreach light in tile
do shading(pixelGBuffer, light)
Forward+ (Tile Based Shading + Forward Shading
- 伪代码
// pre z - pass 1
foreach object in scene
if object.z < depthBuffer.z
do depthOnly(object)
// light culing
// method 1 - screen space
foreach tile in screen
foreach light in scene
if light in this tile
tile += light
// pre z - pass 2
foreach object in scene
if object.z == depthBuffer.z
foreach light in tile
do shading(object, light)
Cluster Based Shading (基于tile和深度优化灯光裁剪
- 伪代码
// build clusterArray
// light culling
foreach cluster in clusterArray
foreach light in scene
if light in this cluster
cluster += light
do shading(clusterArray)
-
Cluster 的构建
- 基于视线方向,将Tile做深度上的切割(每一个三维的块叫Cluster
- 不同深度的选择方法
- 基于NDC:近平面Cluster小且密,远平面大且疏,非线性
- 基于ViewSpace:近平面Cluster大且疏,远平面小且密
- 基于指数:用指数抵消基于NDC的非线性
-
优点
- 支持大规模光源数量
- 缺点
- Cluster构建有固定开销
- 光源裁剪开销大
- 适用场景
- 适合光源数量多的场景
- 对移动端不友好
高效的渲染算法要点总结
- 适当的网格管理和剔除操作
- 减少不必要的像素着色器调用
- 减少着色期间的光照计算数量
- 减少不必要的IO读写