GAMES202.闫令琪.14.工业界算法实现

  • https://www.bilibili.com/video/BV1YK4y1T7yY

工业界算法实现

  • A Glimpse of Industrial Solutions (from the scientific perspective)

AA

  • Anti-Aliasing:反走样

TAA

  • Temporal Anti-Aliasing
  • TAA 算法的成功,才有了 temporal 思想在 RTRT 中的应用
  • 走样的来源:对于每个像素的采样数不够(采样定理)
  • 解决思路:使用更多的样本
  • temporal AA:使用更多的样本,但是是使用更多上一帧(以及之前帧)的样本
    • 思路和 RTRT 中是一样的

静止场景

  • 怎么复用上一帧的样本?
  • 一种想法,每一帧采不同的区域
    • 连续 4 帧,分别采样 左上、右上、右下、左下(移动的 sampling pattern)
    • 复用上一帧,递归形成复用之前所有的样本的 sampling

  • 为什么不随机生成呢?
    • 相对均匀分布
    • 如果随机会引入一些额外的高频信息,效果可能不太好

运动场景

  • motion vector
  • temporal 信息不可用的时候,也是使用 clamping 的方法
    • 基本上和 RTRT 中的思路一致

MSAA 和 SSAA

  • SSAA:Supersampling
    • 渲染的时候,使用更高的分辨率,在渲染结束后,降采样到要求的分辨率
    • 正确的,效果非常好,但是开销非常大
  • MSAA:Multisampling AA
    • 一个 primitive 只会进行一次 shading
    • 下图中,SSAA 需要做 4 次 shading,MSAA 只需要做两次

  • MSAA 支持空间上的复用
    • (1)(2) 中间的两个采样点可以被视为对 (1) 的贡献,也能被当作对 (2) 的贡献
    • 复用了中间两个点

  • https://www.sapphirenation.net/anti-aliasing-comparison-performance-quality

图像上的 AA

  • 先渲染得到带锯齿的结果图,然后在图像上进行反走样处理
  • 最流行的方法:SMAA(Enhanced subpixelmorphological AA)
  • 发展历史:FXAA \(\to\) MLAA(Morphological AA)\(\to\) SMAA

SMAA

  • http://www.iryoku.com/smaa/
  • 先检测出来边界,然后根据找出来的边界,根据占比上色
    • 矢量化的过程

  • 效果非常快
  • 不能对 G-Buffer 做反走样,反走样了则失去了原来的意义

Temporal Super Resolution

  • 超分辨率:Super Resolution(Super Sampling)
    • 字面理解:提高分辨率

DLSS

  • Nvidia
  • DLSS 1.0:硬猜,通过神经网络学习到一些结果,将模糊的边缘换成不模糊的边缘
    • 完全数据驱动
  • DLSS 2.0:使用更多 Temporal 的信息
    • 分辨率提高,变模糊,等价于是采样不足,试从上一帧中获取信息
  • 核心思想就是利用 TAA
    • Temporally reuse samples to increase resolution
  • DLSS 面临的另外一个问题,如果时间的信息不可用,不能使用 clamping 的方法
    • 对 temporal 的信息利用更加严格
    • 我们实际上需要的是一个增大了分辨率的结果,我们需要知道一些更细致分辨率的值,如果我们不能够在时间上获取到这些信息,盲目的使用周围的值去猜,这样会导致模糊的结果
      • 也就是说新的值和原来的值本质上是不同的,更细致的分辨率有更多细节
    • 因此我们需要找一个比 clamp 更好的方案(当 temporal failure 的时候)

  • 当前帧和上一帧的采样信号 \(\to\) 得到一个当前帧增加了采样点的值
    • DLSS 的网络没有输出具体的颜色值,而是告诉我们应该怎么去使用上一帧的信息

效果对比

  • 540p Bicubic Upsampled to 1080p

  • 540p to 1080p DLSS2.0

  • 1080p with TAA

  • DLSS 2.0 的效果可能更加锐利,因为 Temporal 的复用可能提高的分辨率不止 2x

其他

  • DLSS 网络跑得快,具体怎么实现不清楚
    • Network inference performance optimization (classified)
  • AMD 也有 DLSS
    • AMD:FidelityFX Super Resolution
    • 同样性能的 CPU,AMD 的价格大概在 Nvidia 的一半价格
  • Facebook:Neural Supersampling for Real-time Rendering [Xiao et al.]
    • 效果不太好,实现上更像 DLSS 1.0,工业界不好用

避免没有意义的 shading

Deferred Shading

  • 延迟渲染
  • 让 shading 变得更加高效,速度更快
  • 传统的光栅化渲染管线
    • Triangles -> fragments -> depth test -> shade -> pixel
  • 延迟渲染的想法
    • 在传统的光栅化渲染管线下,只有对视点可见的点的 shading 才是真正有效的,其他点的渲染本质上都是是无用功
  • 最坏的情况
    • 对于每一个 fragment,都是从远到近渲染的,这样做了很多无用功
    • 这样每一个点都得做 shading
    • 复杂度:O(#fragment \(\times\) #light)
  • 延迟渲染的基本想法
    • 大部分的 fragment 在最终的 image 中是不可见的
    • 我们只需要渲染在最终的 image 中可见的 fragment

思路

  • 光栅化两次
  • 第一次光栅化
    • 只生成 depth-buffer
    • 不做 shading
  • 第二次光栅化
    • 给通过深度测试的 fragment 进行 shading
    • 因为对于每一个像素,能够通过深度测试的 fragment 只会有 1 个
  • 延迟渲染的基本想法
    • 一次光栅化的开销比对大量不必要点的 shading 计算开销要小
    • assume rasterizing the scene is way faster than shading all unseen fragments (usually true)
  • 复杂度:O(#vis. fragment \(\times\) #light)
  • 问题
    • 我们做不了 AA(G-Buffer 不能做 AA)
    • 但是可以通过 TAA 或者图像空间上的 AA,AA 的问题能够被很好的解决
  • 因此延迟渲染成为工业界的标配

Tiled Shading

  • 优化光源
  • 把屏幕切分为若干个 tile(大概每个 \(32\times32\)),每个小块单独做 shading
  • 这样子的方法可以减少每一个小块需要考虑的光源数目
  • 如下是 frustum 的俯视图

  • 对于每一个小条,不是所有光源都会影响到它
    • 光源的平方衰减
      • 上面的圆圈表示每一个光源的覆盖范围(球投影成圆)
    • 上面的数字表示影响到这个光源的光源个数
  • 复杂度:O(#vis. frag. \(\times\) avg #light per tile)

Clustered shading

  • 想法和 tiled shading 类似
  • 深度上也切片
  • 一个格子可能包含多个像素,前面可能不会把后面整个各自都遮挡住

Level of Detail

  • LoD
    • 例如 mipmap 就是一个 level of detail
  • 在具体使用的时候,选择正确的层级去使用,这样能够节省计算的效率
  • RTR 工业界中把这种在对不同层级细节的使用称为 cascaded
  • shadow map 可以用来做 LoD

Cascaded Shadow Map

  • [Dimitrov et al., Cascaded Shadow Maps]
  • 离视点近的物体使用高分辨率的 SM,离视点远的物体使用低分辨率的 SM
    • 下图中,三角形为 frustum,红色使用高分辨率 SM,蓝色使用低分辨率 SM

  • 实际应用中我们很难生成一张变分辨率的 SM,因此实际应用会生成多张不同分辨率的 SM
  • 针对不同距离,我们使用不同分辨率的 SM
  • 范围会有一些重叠
    • 保证切换 SM 时能够平滑过渡
    • 重叠区域使用两个 SM 混合的效果

Cascaded LPV

  • [Anton Kaplanyan, Light Propagation Volumes in CryEngine 3]
  • 近处比较小,远处比较大

Geometric LoD

  • 高模(三角形多的模型)、低模(三角形少的模型)
  • 预先生成一系列的不同三角形数的模型
  • 可以对一个物体的不同部分使用不同精细程度的模型细节
  • UE5 的 Nanite 就是利用这些原理实现
  • 对于引擎来说,技术实现是难点

Cascaded 的问题

  • 在不同层级之间切换的时候可能会有问题(popping artifactss)
    • 通常的方法可以在边界的地方使用 blending 的方法
    • Popping artifacts
      • TAA 处理(复用上一帧的信息)

引擎实现的难点

  • 一个物体的不同部分使用不同层级的 LoD,怎么保证相接的地方是没有缝的?
  • 如何动态加载和调度不同层级的资源?
    • GPU 容量有限
  • Representing geometry using triangles or geometry textures?
    • 怎么表示几何形体?三角形?几何纹理?
  • 引擎实现的加速
    • clipping 裁剪
    • culling 剔除(背面剔除)

全局光照的解决方法

  • SSR 屏幕空间光线跟踪
  • 没有一种简单的 GI 方法能够解决所有的场景
    • RTRT可以,但是现在还是太慢了
  • 工业界经常把多种方法混合起来使用
  • 一个 GI 的解决方案
    • SSR 得到近似的 GI
    • 对于 SSR 失败的地方,是用其他方式补充
      • hardware (RTRT) or software ray tracing
  • 软件光追
    • HQ SDF for individual objects that are close-by
      • 高质量的有向距离场
    • LQ SDF for the entire scene
    • RSM if there are strong directional / point lights
      • 手电筒
    • Dynamic Diffuse GI(DDGI)
      • Probes that stores irradiance in a 3D grid
      • 利用这些探针去照亮整个场景
  • 硬件光追
    • Doesn’t have to use the original geometry, but low-poly proxies
      • 使用简化的模型
    • Probes(RTXGI)
  • 以上红色部分是 UE5 的 Lumen 实现

课程没有涉及的部分

  • Texturing an SDF
  • Transparent material and order-independent transparency
  • Particle rendering
  • Post processing (depth of field, motion blur, etc.)
  • Random seed and blue noise
    • 蓝噪声:
  • Foveated rendering
    • 注视点投入更多渲染的算力
  • Probe based global illumination
  • ReSTIR, Neural Radiance Caching, etc.
  • Many-light theory and light cuts
  • Participating media, SSSSS
    • 参与介质
    • 次表面散射
  • Hair appearance
  • ......