1. 简介
在计算机图形学中 shading 表示对受光物体的渲染. 主要有几个步骤:
- 计算几何多变形(Mesh)
- 决定表面的材质特性.如法线 / 双向反射分布函数 (BRDF)
- 计算入射光照
- 计算光照的表面的影响. 并最终显示.
一般渲染引擎,渲染场景中的物体的时候,是将这四步一次执行完的。
延迟渲染则将 前两步和 后两步 分开到渲染管道相互独立的两个部分来执行。
2. 背景介绍
前向渲染有多种问题[1]:
- 计算每个几何体受那些光影响耗费了CPU的时间,更坏的是,这是个O(n*m)的操作
- Shader经常需要 超过一次以上的Pass来渲染光照,渲染n个灯光,对于复杂的Shader,可能需要O(n)次运算
- 增加新的光照模型和新的光源类型,可能需要改变所有Effect的源文件
- Shader很快就将达到或者超出SM2的指令限制
我们无法控制同屏可见的玩家数量、无法控制同屏会有多少特效和光源
由于 传统前向渲染缺乏对环境的控制,且对于光源的复杂度难于估量
所以选择 延迟渲染
这可以让我们的画面更接近于当今顶尖的游戏引擎,并且 让光照所耗费的资源独立于场景的几何复杂度
延迟渲染需要显卡提供MRT的支持
延迟渲染的好处:
- 光照所耗费的资源独立于场景复杂度,这样就不用再费尽心机去想着处理那些光源影响几何体了
- 不必要再为几何体的受光提供附加的Pass了,这样就 节省了Draw Call 和状态切换的数量
- 在增加新的光源类型和光照模型时,材质的Shader不需要做出任何改变
- 材质Shader不产生光照,这样就节省了计算额外的几何体的指令数
3. 基本原理
- 目前我们看到最终画面都是2D的,只能看到有限的像素数,理论上我们只要处理(指光照,阴影处理)最终我们可以看到的点的效果就够了,多余的处理是浪费的。
- 延迟渲染: 它先将摄像机空间的点光栅化转化成屏幕坐标后再进行处理。这样就能减少处理的次数,从而提高效率。
- 把处理流程放在了后面,那么处理所需要的参数也必须带到后面的流程. 使用MRT(multi target render)就很重要,RT占用的显存越大,对显卡的的带宽要求也就越高. 后面的处理至少需要空间位置信息,可以通过Depth(至少16位) 获得,其他可以将 法线信息(normal),高光信息(specular),AO系数,diffuse,自发光(emissive),材质编号等信息放入MRT中 。
延迟渲染可化为为 四个阶段:
- Geometry : 将本帧所有的 几何信息 光栅化到G-buffer。包括位置,法线,贴图等。
- Lighting : 以G-buffer作为输入(位置,法线)进行 逐像素的光照计算 将 diffuse lighting和specular lighting 结果分别保存在两张RT上作为lighting buffer.
- Composition : 将G-buffer中的 贴图buffer 和 lighting buffer 融合,得到渲染结果。
- Post-processing : 后处理 如HDR SSAO Blur Bloom等.
4. 延迟渲染核心部分
4.1 G-buffer
- Geometry阶段将几何信息渲染到 multi render target 上 (MRT). 当前最后支持4个?
- MRT中必须的信息:position(depth), normal, diffuse(texture)
- 可能需要的信息:specular, power, emissive, ao, material id
4.2 光照计算以及相关优化
使用延迟渲染技术最大的好处就是可以渲染光照极为复杂的场景。
这里场景中的 光照可以分为两类 :
- 影响 整个场景的scenelight。
- 如directionallight。
- 渲染一个 screenquad,逐像素光照计算
- 另一类是 只影响一部分区域的locallight
- 如点光源、聚光灯、和特效等等。
- 这些locallight只影响到屏幕上的某些像素,当然不需要逐像素的进行光照计算。
- 最简单的方法是 绘制这些光源的包围体 (点光源的包围体是球,聚光灯的包围体是圆锥) ,包围体的大小要大于等于光源的衰减范围。这些包围体经过变换投影到屏幕上的对应区域,随后在pixelshader中计算光照.
优化:
- 光源包围体的 视锥剔除 ,遮挡剔除。
- 光源包围体 投影后很小时剔除;若干个靠的比较近的小光源合并成一个较大的光源
- 光源包围体的 backfaceculling 背面剔除
- 屏幕空间中没有被光源照到的,或者被更近的物体遮挡住的像素不需要光照计算,因此可以逐像素的深度剔除
- a. 使用正确的stencillightvolume
- b.使用ztest,可以得到“一定程度上正确”的结果
4.3 阴影的计算
-
光照计算的同时计算阴影。使用传统的shadowmap,预先生成一张阴影图(相关)
-
考虑在编辑场景的时候指定那些重要的光源才会产生阴影。在计算shadowmap时要针对光源的bindingvolume进行剔除。
-
方向光和聚光灯可以使用基本的Shadow Map投影(正交投影,透视投影)
-
点光源会复杂一些,需要使用Cube Shadow Map
5 延迟渲染优缺点分析
延迟渲染优点:
- 光照的开销与场景复杂度无关;
- Shader可以访问深度和其他像素信息
- 每个像素对每个光源仅运行一次. 那些被遮挡的像素是不会被光照计算到的
- 材质和光照的Shader完全分开
延迟渲染还需要克服的主要障碍:
- 较高的显存带宽占用
- G-buffer消耗较多的填充率,这个问题在游戏机上比较严重
- 无硬件反锯齿的支持
- 对Alpha Blend支持较差
解决方案:
-
增强了MRT的性能. DX10和SM4都提供了GPU支持的整数处理,以及从深度缓冲中读取数据。所有这些都可以减少显存带宽。当提供了新的硬件和特性时,性能自然就会提升。
-
在合适的Filter作用下,精确的边缘检测可以减少几何体边缘的锯齿。
-
对不透明物体采用延迟渲染,透明物体采用正向渲染,可以解决Alpha Blend的问题
参考文献:
[1]http://blog.csdn.net/noslopforever/article/details/3951273
[2]http://www.opengpu.org/forum.php?mod=viewthread&tid=434
[3]http://blog.csdn.net/pizi0475/article/details/7521394
[4]http://blog.csdn.net/Garuda/article/details/5273106
[5]http://blog.sina.com.cn/s/blog_766f82770100p2kc.html
[6]Akenine-Möller T, Haines E, Hoffman N. Real-time rendering 3 [M].