中EN
概念页

延迟着色

Deferred Shading

延迟着色先用一遍几何 pass 把所有可见表面的材质参数写入多张渲染目标(G-buffer),再以后处理方式对这些存储值逐光源计算光照,从而把"几何可见性"与"光照"彻底解耦,并把材质与光源分离。它避免了着色的过度绘制、简化了着色器管理、天然适合贴花,但 G-buffer 占用显存和带宽,且难以直接支持透明和 MSAA。本页也覆盖前向渲染下限制光源影响范围的基础手段与"光照预通道 (light prepass)"类混合方案。

背景:多光源的代价(20 章引言)

  • 多光源可写成支持多光源的单遍着色器,或多遍着色(每个光源一遍、结果累加)。后者每个着色器更简单,但 50 个光源意味着每个物体 50 遍顶点与像素处理;单遍着色器要包含所有光源类型并逐一判断,会很复杂。
  • z-prepass 先只写深度、再完整着色,把"找可见几何"与"着色"分开,这一解耦思想贯穿全章;但几何要渲染两遍,曲面细分、蒙皮等昂贵网格代价可观;alpha 裁剪物体在每遍都要读纹理 alpha,否则只能留到第二遍。因此有时只在预通道画大遮挡物。AO、反射等屏幕空间效果也可能需要完整预通道。
  • 限制光源范围:每个局部光源只影响一定半径的球(或锥等形状),超出后贡献可以忽略。半径常只由强度决定;Karis 指出光泽镜面材质会让半径变大,极光滑表面半径可能趋于无穷,只能改用环境贴图等。
  • 每网格光源列表:相当于网格与光源的碰撞检测。问题是物体或光源移动会改变列表;为性能合并的大网格可能包含场景中大部分光源(可在合并后再按空间切分)。
  • 烘焙到世界空间结构:《正当防卫 2》用俯视世界网格,每格 4 m × 4 m,存为 RGBA 纹理的一个纹素,每格最多 4 个光源;多层建筑会很快超出容量。
  • 目标是高效处理动态网格与动态光源,并且性能可预测。《DOOM》(2016)部分关卡有 300 个可见光源,《奇点灰烬》某些场景有 10,000 个;粒子、光照探针也可视为短程光源。

基本流程(20.1 节)

前向着色在一遍中取材质参数并应用光源;延迟着色在第一遍几何 pass 中生成并存储可见物体的所有材质参数——位置(以深度存储)、法线、纹理坐标、各种材质参数——之后模型本身不再需要,光照以后处理方式施加到这些存储值上。

flowchart LR
  A["几何 pass: 光栅化所有不透明物体"] --> B["G-buffer: 深度, 法线, 反照率, 粗糙度, 金属度 ..."]
  B --> C["光照 pass: 对每个光源绘制覆盖其影响区域的代理几何"]
  C --> D["读取 G-buffer 计算光照并累加"]
  D --> E["前向渲染透明物体, 后处理"]

如上图。几何 pass 仍有过度绘制,但每次只是把值写入缓冲,比计算一组光源便宜得多;也减少了前向着色中 2×2 quad 部分在三角形外仍需完整着色的浪费——设想每个三角形只覆盖一个像素,前向着色会算 4 个完整样本丢掉 3 个,延迟着色的被丢弃样本代价低得多。

G-buffer(geometric buffer)可以存程序员需要的任何东西,每张是一个独立渲染目标,通常 3~5 张,也有多达 8 张的系统;目标越多带宽越大,越容易成为瓶颈。例如《彩虹六号:围攻》除深度与模板外使用 4 张 RT:世界法线 (RGB10)、基础色 (sRGB8)、金属度、光泽度、cavity、速度、GI 配置等。可用低精度或压缩减轻开销;法线常用世界空间八面体映射,精度高且编解码快。

光照 pass 的优化

逐光源绘制全屏四边形、每个像素判断是否在光源范围内,是最低效的用法,可能比前向着色还慢(多了 G-buffer 写和读)。改进:

  1. 计算光源球的屏幕包围矩形,只绘制这块四边形;画椭圆更紧。
  2. 利用深度:绘制粗略包围球网格;若球被深度缓冲挡住,则光源体积在最近表面之后,没有影响。一般地,若球在某像素处的最小与最大深度与最近表面不重叠,光源就影响不到该像素。"表面与光源的深度重叠测试"会在后续算法中反复出现。

优点

  • 光照与材质强分离:每个着色器只负责参数提取或光照,更短更快,便于优化;寄存器用量决定占用率。新增一种光源或材质只需加一个着色器,而不是每种组合一个。
  • 前向着色要么一个覆盖所有组合的巨型着色器(动态分支常慢很多),要么大量专用着色器(难生成和管理),并更频繁地切换着色器。
  • 每个光源单独一遍时,内存中一次只需一张阴影贴图(但在后续按组评估光源的方案中这一优势消失)。
  • 天然适合 贴花渲染。

局限

问题说明与对策
材质单一基础版只有一种参数固定的材质着色器;可逐像素存材质 ID 或掩码,按 ID 改变计算甚至改变 G-buffer 内容(例如同样 32 位一种材质存第二层颜色与混合因子,另一种存两个切线),代价是更复杂的着色器
显存与带宽G-buffer 很大、反复访问;用低精度、压缩缓解
透明每像素只存一个表面;常规做法是不透明用延迟、透明用前向。早期系统需对透明物体应用全部光源;现在有光源剔除方案,也可存逐像素透明表面列表实现纯延迟,但常态是按需混合延迟与前向
MSAA前向 N×MSAA 只需每像素 N 个深度和颜色样本;延迟若在 G-buffer 存全部样本,内存、填充率、计算都很贵。对策:边缘检测近似边缘覆盖、形态学后处理抗锯齿、时间抗锯齿;或检测含边缘的像素/瓦片,只对它们做多样本计算(用模板标记,或用计算着色器把边缘像素移到线程组内存列表里流式处理)

光照预通道与 L-buffer(20.3 节开头)

早期混合方案在材质与光照存储之间折中:例如只有漫反射项受纹理影响时,先对每个光源分别累加漫反射与镜面项到L-buffer(常见为漫反射颜色加镜面强度,共 4 个值可用加法混合写入一张缓冲),最后读一次纹理颜色乘漫反射项再加镜面项。纹理只用一次,每个光源访问的 G-buffer 数据更少,省带宽。这类方法称为延迟光照、pre-lighting 或 light prepass。变体包括低分辨率 G/L-buffer 加双边上采样(光照变化剧烈时如反射表面上的粗糙度或法线贴图会有瑕疵)、对反照率用 Y'CbCr 子采样。局限是材质和光照模型可能受更多限制:转向基于物理的材质后需要存储镜面反射率以计算菲涅耳项,这促使一些团队从 light prepass 转向完整延迟着色。

何时选择

光源少、过度绘制少时延迟着色可能总体更慢;只有太阳一个光源时不需要光源剔除预处理。几何处理复杂或表面着色昂贵时,延迟着色能避免过度绘制、减少程序与状态切换等驱动开销,并允许用更少调用渲染更大的合并网格。同一帧里可以混用多种方法,最佳组合可能因物体或光源而异。光源很多时进一步使用 分块着色 与 分簇着色。

GEA 的视角:G-buffer 与光照预通道(卷 II 12.5.12.1、12.5.12.3)

  • 前向渲染的低效(卷 II 12.5.12):先给三角形的顶点着色,到光栅化阶段才发现整个三角形被 z 测试剔掉;early-z 能消掉部分无用的像素着色但并不完美;要处理大量光源,还会冒出大量顶点和像素着色器版本(不同光源数目、光源类型、蒙皮权重数……)。
  • G-buffer:先不管光照,高效渲染场景,把光照所需的信息存进"深"帧缓冲 G-buffer,再用它做光照与着色。GEA 认为这通常比在观察空间里做光照高效得多,避免了着色器变体膨胀,并且能比较容易地做出一些漂亮的效果。物理上它可以是一组缓冲,概念上是每像素一组丰富的属性:深度、观察空间或世界空间法线、漫反射色、高光指数,甚至 PRT 系数(卷 II 12.5.12.1)。
  • GEA 以 Guerrilla Games《杀戮地带 2》为例,展示的 G-buffer 分量有反照率、深度、观察空间法线、屏幕空间二维运动向量(用于运动模糊)、高光指数和高光强度。
  • 光照预通道 (light pre-pass) 分三阶段(卷 II 12.5.12.3):
    1. 画一遍几何,只往小得多的 G-buffer 里写少量信息(通常只有深度、法线、高光指数);
    2. 逐光源处理,结果存进屏外渲染目标;
    3. 再画一遍几何,用前向风格着色,从屏外渲染目标读光照。 优点是 G-buffer 小、带宽低,也更容易支持多种材质;缺点是要画两遍几何,顶点很重的场景可能吃不消。GEA 引用了 Insomniac 在 GDC 2009 的《抵抗 2》预光照演讲。
  • 与本页的关系:本页「光照预通道与 L-buffer」描述的累加漫反射与镜面项到 L-buffer、最后乘纹理色的方案与 GEA 的三阶段描述是同一类思路;GEA 明确了"几何画两遍"的代价,RTR4 侧重带宽与纹理只读一次的好处。

LearnOpenGL 的视角:G-buffer MRT、光照体积与前向混合(Advanced Lighting / Deferred Shading)

来源:Deferred Shading;摘录 Advanced Lighting — Deferred Shading。

前向:每物体 × 每灯 × 多片元浪费。延迟:几何 pass 用 MRT 写入 G-buffer(位姿/法线常用 RGBA16F,albedo+specular 可打进一张 RGBA8)→ 光照 pass 全屏四边形按像素采 G-buffer,每像素只算一次可见片元光照。

局限:内存大、无传统混合、MSAA 难。做法:glBlitFramebuffer 拷几何深度到默认 FBO,再前向画需要混合/特殊着色的物体(如灯立方体)。

光体积:由衰减解半径(亮度阈约 5/256);shader 里 if(distance<radius) 在 GPU 上常无效(锁步执行)。正确做法:按半径缩放球体,延迟光照 shader 画球体(建议画背面),片元自然覆盖受影响像素,复杂度近 物体+灯。进阶:tile/cluster deferred。法线/视差可在几何 pass 输出世界法线或先偏移 UV。链 分块着色、分簇着色、UE5 渲染架构。

GPU Gems 的视角:Tabula Rasa 的生产级延迟管线(GPU Gems 3 第 19 章)

来源:Rusty Koonce《Deferred Shading in Tabula Rasa》;摘录 Chapter 19. Deferred Shading in Tabula Rasa — Rusty Koonce。接 Shishkovtsov《S.T.A.L.K.E.R.》一章之后的工程经验,与上文 LearnOpenGL/RTR/GEA 的 G-buffer 理论对照。

MMO 无法控制同屏人数与灯数,前向照明开销随几何×灯数恶化,故主路径改延迟(要求 SM3),前向仅作半透明与低配回退。材质与光照彻底拆开:加新灯型不必改材质着色器。实践中的灯型包括双向平行光(正/背色近似环境反射)、Globe Map(立方体/2D 给灯光染色或假阴影)、盒灯(局部平行光+衰减)。阴影全部动态阴影图(无 lightmap),静态/动态投射体分开;阴影图池化并按优先级分帧重建。

深度与法线缓冲的额外价值:水面按眼空间厚度做岸线与折射判定;用邻域深度梯度相对变化 + 法线夹角做分辨率无关的边缘权重,再与邻像素双线性混合冒充抗锯齿。带宽是第一瓶颈——分辨率几乎线性决定成本;漫反射/高光分两张累加 RT,材质属性用访问函数封装以免改 MRT 布局时改全体着色器。半透明仍只能前向,发丝与植被改 alpha test 进延迟以保证进阴影;植被淡入用缩放代替真正混合。稳定阴影需量化光源矩阵,避免亚像素抖动。

GPU Gems 的视角:S.T.A.L.K.E.R. 延迟着色奠基(GPU Gems 2 第 9 章)

来源:Oles Shishkovtsov《Deferred Shading in S.T.A.L.K.E.R.》;摘录 Chapter 9. Deferred Shading in S.T.A.L.K.E.R. — Oles Shishkovtsov。Gems3 Tabula Rasa 章的直接前传:全动态光照的生产级延迟引擎。

动机不只是「灯光与几何解耦」,更是砍掉动态阴影带来的 CPU batch,并避免前向里每个灯重复跑一遍昂贵材质。破除迷思:在中等过度绘制下延迟并不更慢;带阴影的平行光(太阳)仍可用模板跳过天空、背光与 AO=0 像素,实测约 2×。材质不是改光着色器排列组合,而是 G-buffer 写 material ID,灯着色器查表——等于把前向「灯改材质」倒过来。

G-buffer 选型宁可选解码简单的胖格式(眼空间位置+AO、法线+材质用 A16R16G16B16F),也不要为省带宽选难解的打包。全向阴影当六盏聚光灯更利于过滤与打包。虚拟位置(沿法线按高度微移)改善视差与阴影粉刺。边缘检测 AA、Bloom 曝光、半透明仍走无影前向。与 延迟着色 上文 Tabula Rasa 对照:STALKER 更偏 DX9 极限优化与材质 LUT;TR 更偏灯型扩展与分辨率无关边权。

  1. realtime_rendering_4ed.pdf 第 20 章 Efficient Shading
  2. Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 12 章 12.5.12.1、12.5.12.3 节
  4. Chapter 19. Deferred Shading in Tabula Rasa — Rusty Koonce
  5. developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-19-deferred-shading-tabula-rasa
  6. Chapter 9. Deferred Shading in S.T.A.L.K.E.R. — Oles Shishkovtsov
  7. developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-9-deferred-shading-stalker
  8. Advanced Lighting — Deferred Shading
  9. learnopengl.com/Advanced-Lighting/Deferred-Shading

相关页面

图形学像素着色器Pixel Shader像素着色器(OpenGL 里叫片元着色器)对光栅化产生的每个片元运行,用插值后的顶点数据算出颜色,也可以输出不透明度、修改深度或直接丢弃片元。多渲染目标让它一次输出多组数据,催生了延迟着色。它通常只能写自己所在的像素,但能通过 2×2 quad 拿到相邻像素的导数。图形学分块着色Tiled Shading分块着色把屏幕划分为瓦片(如 32×32 像素),先为每个瓦片建立可能影响它的光源列表,着色时每个像素在一次着色器调用中只遍历所在瓦片的列表。它可用于延迟着色(tiled deferred),也可用于前向着色(tiled forward,又称 Forward+)。配合 z-prepass 得到的瓦片深度范围可进一步剔除光源,但深度不连续会削弱效果,于是出现 HalfZ、2.5D 剔除等改进。图形学分簇着色Clustered Shading分簇着色把整个视锥(而不只是屏幕平面)划分为三维单元——簇 (cluster),按簇建立光源列表。与依赖场景几何深度的分块着色不同,簇的划分与几何无关,可只由视图和光源计算,因此对相机位置的性能波动更小、对深度不连续更稳健,并为不透明、透明、体积物体提供统一的光照方案。它同样可配合前向或延迟着色,并衍生出 z-binning、光源树等更省内存的变体。本页还汇总了各类多光源方案的对比。图形学贴花渲染Decal Rendering贴花 (decal) 是叠加在表面上的图案或纹理,如轮胎印、弹孔、玩家喷漆、标志。贴花可只改颜色(纹身)、只改凹凸(压印标志)或换成完全不同的材质(车窗贴纸),可多个叠在同一几何上,也可横跨多个模型。主流做法是用有向盒做正交投影的投影贴花;延迟着色把贴花效果直接写进 G-buffer,分簇前向着色则把贴花像光源一样放进簇列表。图形学延迟纹理与可见性缓冲Deferred Texturing & Visibility Buffer延迟着色避免了着色的过度绘制,但生成 G-buffer 时仍有过度绘制:先画的物体读了大量纹理,被后画的物体挡住后这些带宽全部浪费。延迟纹理只用一遍几何 pass、存极少的数据(纹理坐标与切线基,或仅三角形与实例 ID),直到着色时才读纹理。由于 GPU 算力增长快于带宽,让瓶颈落在计算而非缓冲访问被视为面向未来的做法。图形学像素与帧缓冲优化Pixel & Framebuffer Optimization需要着色的像素通常远多于顶点,所以像素处理优化往往最划算。核心手段:保证占用率以隐藏纹理延迟、按距离切换着色器 LOD、利用 early-z 并通过从前往后排序或 z-prepass 减少过度绘制、缩小帧缓冲每像素存储(色度子采样、YCoCg 棋盘),以及只在需要时开启混合、避免 GPU 回读。几何与光栅化阶段的常用优化也一并列出。图形学抗锯齿Antialiasing渲染本质上是采样,采样频率不足就会混叠(锯齿、闪烁的"萤火虫"、车轮倒转)。屏幕空间抗锯齿在每个像素取多个样本并加权求和:超采样最直接但最贵,MSAA 每像素只着色一次,时间抗锯齿 (TAA) 把样本分散到多帧,形态学方法 (FXAA/SMAA) 作为后处理重建边缘。没有一种方法在所有方面最好。图形学透明渲染与 Alpha 混合Transparency & Alpha Blending本页讲最简单的"视角相关"透明:半透明物体只衰减其后方物体的颜色。z-buffer 每像素只存一个表面,所以透明物体通常要从后往前用 over 运算符混合;顺序无关透明 (OIT) 方法用多遍渲染、逐像素链表或近似公式避免排序,各有内存、性能或准确性代价。预乘 alpha 让过滤、混合和合成更正确高效。图形学顶点压缩与精度Vertex Compression & Precision网格数据像纹理一样可以压缩:传输用的整体压缩(Draco 等)一次性解码,渲染用的定长压缩让顶点着色器在 GPU 上逐顶点解码,从而降低内存、带宽并改善缓存。另一面是精度问题:大世界中单一坐标系会让远离原点的物体抖动,需要相对相机的变换或分段原点。图形学着色模型与光源Shading Models & Light Sources着色模型描述物体颜色如何随表面朝向、观察方向和光照变化。光源通过两个参数与着色模型交互:指向光源的方向 \mathbf{l} 和光的颜色 \mathbf{c}{\text{light}}。方向光、点光源、聚光灯的区别就在于这两个量如何随场景变化;距离衰减和方向衰减函数的选择同时影响画面与性能。图形学GPU 架构案例GPU Architecture Case StudiesRTR4 第 23.10 节剖析三种架构:面向移动设备、以能效为先的 sort-middle 分块架构 ARM Mali G71 Bifrost;NVIDIA Pascal(GTX 1080)的 SM/TPC/GPC 层级与介于 sort-middle 和 sort-last fragment 之间的 tiled caching;AMD GCN Vega 的计算单元、异步计算引擎、DSBR 与 HBCC。硬件厂商通过对尚未制造的 GPU 做大量参数化仿真来决定 MP 数量、缓存、光栅引擎、ROP 数等——各种单元数量的原因归根结底是"这样效果最好"。游戏开发 · UE5Lumen 全局光照与反射Lumen Global Illumination & ReflectionsLumen 是 UE5 默认的全动态全局光照 (Global Illumination, GI) 与反射系统:先做屏幕空间追踪,未命中再对"Lumen 场景"做软件光追(有符号距离场)或硬件光追,命中点的光照从按网格离线放置的卡片 (Card) 构成的表面缓存 (Surface Cache) 中查询,表面缓存的直接与间接光照分摊到多帧更新,从而得到无限次漫反射弹射和全粗糙度范围的反射。游戏开发 · UE5UE5 渲染架构UE5 Rendering ArchitectureUE5 的渲染器是独立的 Renderer 模块,在渲染线程 (Rendering Thread) 上以「场景代理」镜像游戏线程的组件状态,每帧按固定顺序执行深度预通道、G-buffer 基础通道、光照、雾、半透明和后处理。现代渲染代码用渲染依赖图 (Render Dependency Graph, RDG) 声明通道与资源,由 RDG 自动排屏障、复用瞬态内存、并行录制;最终命令经 RHI 线程翻译成 D3D12/Vulkan 等图形 API 调用。默认走延迟着色 (Deferred Shading),也可切换前向着色 (Forward Shading)。综合帧时间预算与渲染性能Frame Budget & Rendering Performance本页把 wiki 中分散在 RTR4 第 18~23 章的性能知识串成一条线:一帧的时间预算由最慢的管线阶段决定,先用毫秒帧时间度量并定位瓶颈,再按瓶颈所在位置——CPU/驱动、几何、像素、带宽/内存——选用对应手段;最后从 GPU 硬件机制(占用率、HiZ/early-z、压缩、分块架构)理解这些手段为何有效。各结论的细节与出处见所链接的概念页。图形学并行图形架构与排序分类Parallel Graphics Architectures & Sort Taxonomy提升图形速度的最佳方式是并行:多个几何单元、光栅化单元和像素处理单元同时工作再合并结果。Amdahl 定律指出串行部分限制总加速比。由于 API 要求按提交顺序处理图元,并行单元之间必须在某处做"模型空间到屏幕空间"的排序,按排序位置分为 sort-first、sort-middle、sort-last fragment、sort-last image 四类,各有负载均衡与带宽取舍。本页还简述光线追踪硬件的共同特征。图形学对象空间与纹理空间着色Object- & Texture-Space Shading对象空间/纹理空间着色把着色计算的频率与几何采样(光栅化)的频率解耦:在物体的参数化(纹理图表)上计算着色并存入纹理,最终光栅化时只查表。思想源自 Pixar 的 Reyes 离线渲染器的微多边形着色。它能消除 quad 过度着色、按屏幕覆盖率控制着色量、在帧间复用着色结果,甚至让着色以低于光栅化的帧率异步运行;代价是物体必须有唯一的 uv 图表、先着色后遮挡带来浪费等。游戏开发 · UE5Substrate 材质Substrate MaterialsSubstrate 用一种更有表现力、更模块化的框架,取代旧材质系统里固定的一组着色模型和混合模式(Default Lit、Clear Coat 等)。材质被看作一块块「物质板 (Slab)」,每块是用有明确单位的物理量参数化的原则化 BSDF,再通过混合、垂直分层等运算组合成图。代价是光照评估更贵,所以提供参数混合和两种 GBuffer 格式(Blendable / Adaptive)来在速度和画质之间取舍。新项目默认启用 Substrate;升级到 5.7 及以后的老项目默认不启用。图形学合并阶段与帧缓冲Merging & Framebuffer合并阶段把像素着色算出的片元颜色和缓冲区里已有的颜色结合起来,同时负责深度测试、模板测试和混合。它通常不可编程但高度可配置,也叫 ROP(光栅操作或渲染输出单元)。帧缓冲是系统中所有缓冲区的总称。图形学硬件光线追踪管线Hardware Ray Tracing Pipeline高端 GPU 提供硬件加速的光线追踪,它像 GPU 中独立于光栅管线和计算管线的另一条管线,但能与它们协调同步。场景几何要先组织成两层加速结构(TLAS 实例层与 BLAS 几何层),光线发射后由 any-hit、closest-hit、miss 等着色器处理结果。由于还不够快,GPU 光追通常与光栅化结合成混合渲染:先光栅化 G-buffer,再对镜面、反射和间接光发射光线。图形学着色频率与材质系统Shading Frequency & Material Systems实现着色时要按"计算频率"划分工作:整个 draw call 不变的放到应用端作为 uniform,其余放在相应的可编程阶段。实践中大多数着色在像素级完成,顶点着色器负责变换和变形。材质系统把面向美术的材质与底层着色器组织起来,处理海量着色器变体的组合问题。图形学环境光遮蔽Ambient Occlusion环境光遮蔽 (AO) 是余弦加权后半球上未被遮挡的比例,用来在光照缺乏方向变化时仍给出形状线索(缝隙变暗)。它由 Landis 在 ILM 为《珍珠港》开发,可离线烘焙,也可在物体空间或屏幕空间动态计算(SSAO、HBAO、GTAO 等)。AO 适合漫反射和平滑环境光,不适合点光源或小面光源的可见性(RTR4 11.3 节)。

被这些页面引用1 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原