GPU Gems 2 · Chapter 9. Deferred Shading in S.T.A.L.K.E.R.
以 G-buffer 和 MRT 把几何属性与动态光照分开,再用光源剔除、stencil mask、材质索引与 shadow map 控制屏幕空间成本。
学习目标
- 能说明 deferred shading 如何把 geometry pass、G-buffer 和 lighting pass 分开
- 能为位置、法线、albedo、gloss、material ID 与 ambient occlusion 设计 MRT 布局
- 能用光源剔除和 stencil mask 限制真正受影响的屏幕像素,并识别阴影造成的额外成本
- 能解释透明 primitive 为什么通常走 forward fallback,以及虚拟位置如何改善 parallax 的光照一致性
forward renderer 在每个物体 pass 中重复做顶点变换、纹理过滤、法线解压和材质计算。↡先把可见表面属性写入中间缓冲、再用屏幕空间 pass 统一计算动态光照的渲染架构将几何与光照解耦:geometry pass 只输出后续需要的属性,lighting pass 读取这些属性为像素累积光照。
1. G-buffer 与 MRT
↡保存每个屏幕像素位置、法线、颜色和材质控制字段的中间缓冲集合可以放 eye-space position、normal、albedo、gloss、material ID 和 ambient occlusion。DirectX 9 的 MRT 允许一次 geometry pass 写多个 render target,但每个额外通道都会增加显存带宽和后续采样。
↡让一个 geometry pass 同时写入多个 render target 的输出机制的布局应从 lighting shader 反推,而不是按“能放多少就放多少”。法线可以编码在 32-bit 或浮点格式中,position 可能需要更高精度;material ID 与 gloss 可以占用空余组件,帮助 light shader 选择不同响应函数。
2. Lighting pass 的屏幕空间预算
↡读取 G-buffer、遍历影响屏幕的光源并累积最终像素光照的后续阶段的理论成本与光源覆盖的屏幕区域相关,而不是与场景中所有物体的数量直接相关。先用 sector/portal、CPU 或 GPU occlusion culling 减少候选光源,再用光源体积和 stencil mask 限制像素。
shadow-casting light 还要生成或采样 shadow map,通常是最大的额外成本。艺术决策也很关键:并非每盏模拟环境光的灯都需要阴影或 glossy specular;将不必要的 shadow light 降为 unshadowed light,收益往往比继续微调 shader 更直接。
3. 太阳、AO 与虚拟位置
方向光常覆盖很大的屏幕区域,但仍可以用 sky mask、背向太阳的 normal 和 AO 为零的像素做 stencil 过滤。先快速标记不可能被太阳照亮的像素,再让复杂 shadow filtering 只运行在剩余区域。
↡沿像素法线按 height 值轻微移动 G-buffer position、让 parallax 细节参与光照和阴影的近似可以改善近距离 parallax 的阴影边界和 surface acne,但它是视觉近似,不能把它当成真实几何位移。位置、法线和 height 的编码必须保持一致,否则光源方向变化时会出现不稳定的阴影。
4. 材质响应与透明边界
deferred 的材质系统通常把 lighting shader 需要的控制量写进 G-buffer,例如 material index、gloss 和 AO;light shader 可以据此查 2D/3D lookup table,而不是为每种材质组合生成一套 shader。这将“材质改变光照响应”反过来组织成“光照读取材质参数”。
透明是架构边界:单层 G-buffer 没有空间保存多个深度排序的透明表面。实际系统可以让透明 primitive 走 forward lighting,通常不共享 deferred 的 shadow 处理;关键是把这条 fallback 当成显式的渲染路径,而不是偷偷覆盖 G-buffer。
5. 动手实验:成本随哪一维增长
调高光源数量,观察 lighting pass 和 stencil affected pixels 增长;调高 overdraw,观察 geometry/G-buffer 固定成本上升;切换 shadow-heavy,观察同一受影响区域的光照成本被放大。数值只是趋势示意,真实结论要回到 GPU profile。
Deferred shading 实验
比较固定 geometry/G-buffer 成本与受屏幕影响的 lighting 成本。
增加光源主要提高 lighting pass;增加 overdraw 主要提高 geometry/G-buffer 成本。阴影质量会放大受影响像素的代价。
小结
- deferred shading 用 geometry pass 写 G-buffer,再在 lighting pass 读取属性累积光照。
- MRT layout 是精度、带宽、解码和材质灵活性的折中。
- 光源剔除与 stencil mask 将 lighting 限制到真正受影响的屏幕区域。
- 阴影、G-buffer 带宽和 overdraw 仍可能成为瓶颈,架构选择必须依赖 profile。
- 透明不适合单层 G-buffer,通常需要 forward fallback;virtual position 只是局部视觉近似。
练习
问题 1|pass 设计 geometry pass 为什么不直接计算所有动态光照,而是把 position 和 normal 写入 G-buffer?
问题 2|通道预算 如果一个 G-buffer 通道还有空余组件,哪些字段适合放进去?放进去前还要检查什么?
问题 3|透明 为什么一层 G-buffer 不能自然表达多个半透明表面?工程上如何处理?
名词解释
本章出现的专业名词,用大白话再讲一遍。
- deferred shading
- 先写表面属性、后按屏幕像素计算光照的渲染架构。
- G-buffer
- 保存位置、法线、颜色和材质控制字段的中间缓冲集合。
- MRT
- 一个 pass 同时写多个 render target 的输出机制。
- lighting pass
- 读取 G-buffer 并累积动态光照的后续阶段。
- stencil mask
- 标记光源实际影响像素、限制后续 shading 范围的掩码。
- virtual position
- 沿法线轻微移动 G-buffer 位置以改善 parallax 光照近似的方法。