01 - 工业界的解决方案
本文将简要介绍实时渲染领域一些工业界的解决方案,如抗锯齿方面的TAA,DLSS2.0;一些渲染方式(延迟渲染,分块渲染,集群渲染);LoD(Level of Detail);全局光照等。
抗锯齿
TAA
TAA(Temporal Anti-Aliasing)的思想启迪了RTRT领域中时间上的降噪方法。产生走样的原因是光栅化过程中每像素采样不足,因此终极解决方案就是使用更多的采样。对于TAA,它会复用上一帧的结果以增加采样数。
如图,假设这是一个静止场景,在TAA前一像素格只有红点,会导致走样。在进行TAA时,它会找到上一帧对应的黄点,黄点又会找到上上一阵的棕点,这样递归找下去后相当于做了两倍的采样。TAA后的结果就不会走样了。
通常找上一帧点的过程是固定的,因为随机找点的效果并不好,例如引入意外的高频信息。如果场景是动态的,可用Motion Vector
。如果采样综合后的值超过了0~255,可用clamp()
操作限制范围。
DLSS 2.0
对于DLSS 1.0,它会为每个游戏单独训练一个模型,然后对每一帧超采样然后缩小,所有的过程都全靠模型“猜”,结果并不怎么好。
而DLSS 2.0则更多利用时域上的信息进行超采样(TAA思想),然后加持深度学习超采样,获得较好的结果。但DLSS2.0还有一个更大的问题,如果时域上的信息出现失效,就不能用clamp()
操作了,因为信息是从低分辨率图片上得到的,还需要考虑从低分辨率拓展到高分辨率的信息是否正确(左图)。因此需要考虑一个更好利用时域信息的方案,这正是深度学习要做的(右图)。
效果很不错:
此外,AMD也有自己的DLSS,即FidelityFX Super Resolution。
渲染方式
延迟渲染
延迟渲染(Deferred Shading),主要目的是节省渲染时间。传统渲染方式中,每个片元都可能要做一次着色(例如从远到近渲染物体),每添加一个光源,就要对所有物体重计算一次光照,很耗时。而延迟渲染则考虑G-Buffer等信息,只渲染可见的片元,以节省渲染时间。
总的来说,延迟渲染就是 进行两次光栅化,它的思路如下:
- 第一次光栅化:不做真正的渲染,只更新G-Buffer(比如深度);
- 第二次光栅化:根据G-Buffer的信息做渲染,以减少不必要的着色。
由于延迟渲染里用的是G-Buffer的信息,因此很难做抗锯齿,但TAA的出现解决了这一问题。
分块渲染
分块渲染(Tiled Shading),基于延迟渲染,将屏幕空间分成32x32个小块,然后进行分块渲染。由于光源有衰减,可认为它们的覆盖范围是一个球,那么每个块只需考虑覆盖到自己的光源即可,进一步节省渲染时间。
集群渲染
集群渲染(Clustered Shading),在分块渲染的基础上,增加以深度值为基础的划分,即把3D空间进行拆分,更进一步节省渲染时间。
LoD
简介
LoD(Level of Detail)在实时渲染领域很重要,类似Mipmap,总是选择最合适的LoD以节省计算量,这种思路也被称为级联(Cascaded)。
思想比较简单,难点是技术实现。
例子
级联阴影贴图,生成多种分辨率的阴影贴图,并根据摄像头和物体的距离灵活选用。但不同分辨率的阴影贴图有重叠区域,在交界处容易出现突变现象,这时候需要使用插值/混合来平滑过渡。
级联LPV,光传播越远使用越大的格子以减少计算量。
模型的LoD,给物体生成精细度不同的模型,根据摄像机离物体的远近等标准渲染对应精细度的模型。而TAA会解决模型切换时的突变问题。
UE5的Nanite就是一个非常牛的实现。
全局光照
SSR,RTRT等方法均有各自的缺陷,一种比较好的做法是将它们结合起来,例如:先用SSR搞一个粗糙的全局光照成果,然后使用软/硬件的光线追踪进行完善。
软光追
- 为近处的物体准备高分辨率的SDF
- 为整个场景准备较低分辨率的SDF
- 为非常强的方向光/点光源准备RSM
- 也能用光照探针(Probes)存储3D网格中的光照信息,这种方法叫做Dynamic Diffuse GI,即DDGI
硬光追
- 使用简化版模型加快速度
- 结合光照探针,这种方法是RTXGI
UE5的Lumen就是一个非常牛的实现。
未提到的话题…
- 给SDF物体上材质
- 透明材质物体的渲染
- 粒子特效渲染
- 后期处理
- 随机数种子,蓝噪声
- Foveated Rendering,在VR中对眼睛盯着的地方集中算力渲染。
- 基于探针的全局光照
- ReSTIR
- Many-light理论和light cuts
- 参与介质,SSSSS(次表面散射)
- 头发渲染
- …
参考资料
- GAMES202: 高质量实时渲染 (ucsb.edu)