28-多光源渲染方案

在现代实时渲染中,处理大量动态光源是一个核心挑战。传统的 Forward Rendering(正向渲染) 在每个物体绘制时遍历所有光源计算光照,其性能开销与 物体数量 × 光源数量 成正比,因此无法高效处理大量光源。

以下是主流的几种方案:


1. Deferred Shading/Deferred Rendering(延迟着色/延迟渲染)

这是最早广泛用于解决多光源问题的方案。

  • 核心思想:将几何处理光照计算分离成两个独立的阶段。

    • 第一阶段(Geometry Pass):遍历所有几何体,但不计算任何光照。 Instead,将表面的各种属性(如位置、法线、漫反射颜色、高光系数等)渲染到一张张单独的缓冲区中,合称为 G-Buffer
    • 第二阶段(Lighting Pass):不再需要场景几何信息。遍历每一个光源,对于每个光源,将其视为一个几何体(如球体、锥体),并在屏幕空间下,根据 G-Buffer 中存储的信息,计算该光源对哪些像素有贡献。每个光源的计算互不影响。
  • 优点

    • 光照计算复杂度与场景复杂度无关,仅与屏幕分辨率光源数量成正比。非常适合处理大量小型光源。
    • 每个像素只计算真正被贡献的光照,效率高。
  • 缺点

    • G-Buffer 占用大量带宽和内存
    • 对透明物体和抗锯齿(MSAA)支持不友好,需要额外方案(如正向渲染透明物体,使用 TAA/FXAA)。
    • 材质类型受限,G-Buffer 的格式固定,难以支持非常复杂、多样的材质(虽然可以通过设计来扩展,但有成本)。

2. Forward+ (Tiled Forward Rendering)(分块正向渲染)

Forward+ 是对传统正向渲染的增强,旨在保留其优点的同时解决多光源问题。

  • 核心思想:它也分为两个阶段,但比延迟渲染更“轻量”。

    • 第一阶段(Depth Pre-Pass):首先,渲染整个场景的深度信息,得到一个深度缓冲区(Depth Buffer)。
    • 第二阶段(Light Culling & Shading)
      1. 分块(Tiling):将屏幕分割成许多个小块(Tiles),例如 16x16 或 32x32 像素的块。
      2. 光源剔除(Light Culling):对每个屏幕块,根据其在世界空间中的视锥体(由块的像素区域和深度范围计算得出),遍历所有光源,找出哪些光源会影响到这个块。为每个块生成一个光源索引列表
      3. 着色(Shading):使用传统的正向渲染流程绘制每个物体。在像素着色器中,不再是遍历所有光源,而是只需加载当前像素所在屏幕块对应的光源索引列表,并只计算这些少数光源的贡献。
  • 优点

    • 克服了传统正向渲染 O(n*m) 的计算复杂度。
    • 支持 MSAA 和任意材质,因为着色阶段仍然是正向渲染,着色器可以非常灵活。
    • 比延迟渲染占用更少的内存带宽(没有大的 G-Buffer)。
  • 缺点

    • 光源剔除阶段需要一定的 CPU 或 GPU 计算开销。
    • 每个像素最终计算的光源数量可能不均匀(有的块光源多,有的块光源少),可能导致性能波动。

3. Clustered Shading(集群着色)

这是对 Forward+ 的进一步优化,解决了其一个主要痛点:在深度方向上划分不够精细。

  • 核心思想:Forward+ 只在屏幕的 2D 空间上分块,而在深度方向上是“一刀切”的。Clustered Shading 在 3D 空间中对视图视锥体进行划分。

    • 不仅沿着屏幕的 X、Y 轴分块,还沿着 Z 轴(深度轴) 进行切片(Slice)。这样形成了一个个 3D 的“集群”(Cluster)。
    • 光源剔除过程是为每个 3D 集群计算其影响的光源列表。
  • 优点

    • 解决了 Forward+ 在深度方向上的浪费问题。例如,一个靠近相机的小块和一个很远的小块,如果包含的光源数量差异很大,在 2D Tiling 中会被同等对待,而在 3D Clustering 中会被区分开,光照列表更精确。
    • 尤其擅长处理光源分布不均匀的复杂场景(如有很多小灯的长走廊)。
  • 缺点

    • 算法实现比 Forward+ 更复杂。
    • 剔除阶段的计算开销更高。

4. Tiled Deferred / Clustered Deferred

这只是上述思想的组合。延迟渲染同样可以受益于分块/集群的光源剔除技术。

  • 核心思想:在延迟渲染的 Lighting Pass 中,不再为每个光源绘制一个全屏的 Light Volume,而是使用计算着色器,对每个 Tile 或 Cluster 进行光源剔除,然后逐块进行光照计算。
  • 优点:进一步提升了延迟渲染在处理极大量光源时的性能,因为它避免了为每个光源绘制其影响范围(Overdraw),而是更精确地计算每个像素受哪些光源影响。

总结与对比

方案核心思想优点缺点适用场景
传统正向渲染逐个物体,遍历所有光源计算材质灵活,支持MSAA,透明物体简单性能与物体×光源数成正比,无法处理多光源光源数量很少的场景(<10个)
延迟渲染将几何和光照分离,使用G-Buffer高效处理大量小型光源,与场景复杂度无关占用带宽大,透明和MSAA支持差,材质不灵活大量小型动态光源的场景(如科幻、霓虹灯)
Forward+屏幕分块,为每个块剔除光源支持MSAA和复杂材质,内存带宽占用低深度方向剔除不精确,性能可能不均需要MSAA、复杂材质且光源数量较多的场景
Clustered在3D视锥体内分块,更精确剔除光源剔除最精确,尤其擅长深度变化大的场景实现最复杂,计算开销最大最通用、高效处理极大量动态光源的方案

现代游戏引擎的选择

  • **Unity (URP/HDRP)**:
    • URP:默认使用 Forward+ (Tiled) 渲染器。因为它需要在移动端和PC端有良好的平衡,并支持多种材质。
    • HDRP:默认使用 Deferred。因为它面向高端平台,需要处理极其复杂的光照和材质(通过多通道G-Buffer实现),并且其透明物体通常用正向渲染进行叠加。
  • Unreal Engine:传统上以延迟渲染为核心,并且其光照计算也使用了分块/集群优化。UE5 的 Lumen 等全局光照系统也构建在延迟管线之上。

结论:
目前,Clustered Shading 被认为是处理大量动态光源最强大和通用的解决方案,无论是与正向渲染结合(Clustered Forward)还是与延迟渲染结合(Clustered Deferred),它都提供了最佳的性能和灵活性,因此被许多3A游戏和现代游戏引擎所采用。Forward+ 是一个优秀的折中方案,而延迟渲染在特定需求下依然非常强大。