Forward、Forward+、Deferred 与混合渲染管线
Forward 和 Deferred 的主要区别,是光照信息在渲染流程中的组织方式。引擎可以按物体、材质和平台组合多条路径,因此实际项目常见的是混合管线。
一、Forward:绘制时直接计算光照
Forward 在绘制物体时运行材质 Shader,并计算该像素受到的光照:
Mesh + Material + Lights
↓
Vertex / Fragment Shader
↓
Depth / Blend
↓
Scene Color场景有很多局部光源时,传统实现可能让许多光照都参与同一批像素的计算。成本会随屏幕覆盖、材质复杂度和光源数量上升。
Forward 的优点是流程直接、没有完整 G-Buffer 的写入成本、透明物体自然适配,也容易保留 MSAA 和材质特例。光源很多时,需要光源剔除、分桶或限制每个对象处理的光源数。
二、Forward+:先筛光源,仍用 Forward Shader
Forward+ 通常先把屏幕划分为 Tile 或 Cluster,计算每个区域可能影响它的光源列表。Forward Shader 再只计算当前像素所在区域的相关光源:
Light Culling:屏幕区域 → 相关光源列表
↓
Forward Shading:材质像素只遍历本区域光源它减少无关光照计算,又保留 Forward 的材质与透明路径,通常不需要保存完整的材质 G-Buffer。代价是增加光源剔除阶段、列表存储和调试复杂度;具体透明路径是否共用光源列表取决于实现。
三、Deferred:先保存表面信息,再计算光照
Deferred 将几何与材质阶段、光照阶段拆开。Geometry Pass 把屏幕可见表面的必要信息写入 G-Buffer,后续 Lighting Pass 再读取这些信息计算光照:
Geometry Pass
写入 Base Color / Normal / Roughness / Depth 等
↓
G-Buffer
↓
Lighting Pass + Light Data
↓
Scene ColorG-Buffer 不一定包含固定字段;格式和精度是画质、带宽、显存与材质需求之间的取舍。Deferred 的收益来自光照计算不再为每个物体重复组织,且容易按屏幕区域剔除光源。
主要代价包括:
- 多个 Render Target 的显存和读写带宽;
- G-Buffer 格式限制了能保存的材质信息;
- 透明物体通常需要额外 Forward Pass;
- MSAA、材质特例和后处理路径更复杂;
- 移动设备上带宽与功耗成本可能抵消光照计算收益。
四、Hybrid:不同对象走不同路径
一种常见组合是:
不透明主材质 → Deferred G-Buffer → Deferred Lighting
透明 / 粒子 / 特殊材质 → Forward Pass
↓
Post Process → UI这不是强制模板。也可以以 Forward 为主,只让大量光源影响的区域使用 Forward+;或只把一类适合 G-Buffer 的不透明对象放进 Deferred。分类依据应写清楚,避免材质任意切换造成难以调试的 Shader 和状态组合。
五、管线对比
| 维度 | Forward | Forward+ | Deferred |
|---|---|---|---|
| 光照计算 | 绘制时逐像素计算 | 绘制时计算筛选后的光源 | G-Buffer 后单独计算 |
| 多光源处理 | 光源多时成本容易上升 | Tile/Cluster 缩小光源集合 | 便于按屏幕空间处理光源 |
| G-Buffer | 不需要 | 通常不需要完整 G-Buffer | 需要 |
| 透明物体 | 直接支持 | 可复用或扩展光源列表 | 通常另走 Forward |
| 带宽压力 | 通常较低 | 增加光源列表读写 | G-Buffer 带宽可能较高 |
| 材质自由度 | 高 | 高 | 受 G-Buffer 与 Lighting 设计影响 |
| 主要复杂度 | 光源循环与排序 | 光源剔除和列表管理 | G-Buffer、光照与例外路径 |
六、从已有 Forward 管线逐步演进
建议先测量现状,再按能独立验证的步骤演进:
1. 建立基线
记录典型场景的 CPU/GPU 帧时、Draw Call、材质和状态切换、光源数量、内存、带宽及设备温度稳定后的表现。先确认主要瓶颈是否确实来自光照。
2. 整理渲染输入
让游戏对象经由稳定快照和 RenderPacket 提交绘制数据,明确 Mesh、Material、Transform、Render Flags 与资源 Handle。把不透明、透明和特殊材质分开组织。
3. 先评估 Forward+
如果主要问题是很多光源被大量无关像素处理,可以先增加 Tile/Cluster 光源列表,保持现有材质 Shader 主体不变。验证光源剔除本身的成本和收益。
4. 只为合适的对象增加 Deferred
选择一类不透明材质,定义最小可用的 G-Buffer,确认它能表达所需材质信息,再增加 Deferred Lighting。不要一开始就把所有材质字段塞进 G-Buffer。
5. 保留 Forward 例外路径
透明、粒子、头发或特殊材质可继续使用 Forward。两条路径共享需要的阴影、深度或光照资源,并在明确的 Pass 边界处合成。
6. 用 RenderGraph 管理资源关系
声明每个 Pass 对 G-Buffer、Depth、Shadow Map、Scene Color 的读写方式,让 Graph 管理执行依赖、Barrier 和临时资源生命周期。RenderGraph 负责组织资源与 Pass,材质分类仍属于渲染策略。
7. 建立平台档位和回退
按照设备能力、带宽预算、目标 API 和测试结果,决定启用 Forward、Forward+ 或 Hybrid。保留可验证的低成本路径,避免不支持某个格式或特性的设备无法渲染。
七、怎样判断选型有效
比较同一场景、同一设备、同一画质设置下的:
- CPU 与 GPU 帧时,以及 GPU 是否出现空闲等待;
- Draw Call、Shader 工作量与光源剔除开销;
- G-Buffer 和其他 Render Target 的内存占用、读写带宽;
- 透明物体、Overdraw、MSAA 与后处理成本;
- 画质差异、功耗、温度以及长时间运行后的性能。
如果 Deferred 节省的光照计算小于 G-Buffer 的读写和带宽成本,它就未必更快。Forward+ 或保留 Forward 可能更合适。
小结
Forward:材质绘制时直接算光照,结构简单、透明友好。
Forward+:先筛选局部光源,再沿用 Forward 着色。
Deferred:先写 G-Buffer,再统一计算光照,多光源处理方便但带宽成本更高。
Hybrid:按对象、材质和平台组合路径,并通过明确的 Pass 边界合成。演进的目标是让管线与负载匹配。选择应由测量结果和设备约束支持,而不是单纯追求某一种管线。


