中EN
概念页

延迟纹理与可见性缓冲

Deferred Texturing & Visibility Buffer

延迟着色避免了着色的过度绘制,但生成 G-buffer 时仍有过度绘制:先画的物体读了大量纹理,被后画的物体挡住后这些带宽全部浪费。延迟纹理只用一遍几何 pass、存极少的数据(纹理坐标与切线基,或仅三角形与实例 ID),直到着色时才读纹理。由于 GPU 算力增长快于带宽,让瓶颈落在计算而非缓冲访问被视为面向未来的做法。

动机(20.5 节)

  • 部分或完整的 z-prepass 能避免被覆盖表面的纹理访问,但许多系统想避免额外几何 pass:顶点数据也耗带宽,几何细密时额外一遍可能比它省下的纹理访问还贵。
  • G-buffer 越多越占内存和带宽。瓶颈总在变化,各种效率方案都是针对特定平台和场景开发的;实现难度、内容制作便利性等人为因素也决定了最终方案。

虚拟延迟纹理(《刺客信条:大革命》)

Haar 与 Aaltonen 维护一张 8192×8192 的本地纹理图集,存放从更大集合中选出的可见纹理,每张 128×128。

存储内容位数说明
(u, v) 图集坐标每分量 16 位13 位寻址 8192 个位置,剩余 3 位(8 级)用于亚纹素精度
切线基32 位编码为四元数
合计64 位只需一张 G-buffer

几何 pass 不读纹理,过度绘制极其便宜;着色时再访问虚拟纹理。mipmap 所需梯度不存储,而是检查邻居像素,用 (u, v) 最接近的邻居现场计算;材质 ID 由所访问的图集瓦片推出(纹理坐标除以 128)。

他们还用四分之一分辨率 + 自定义 MSAA 采样模式:在支持自定义采样位置的平台上把 4×MSAA 设为网格模式,使每个样本正好对应全分辨率像素的中心。(u, v) 和切线基可在表面上无损插值;8×MSAA(相当于每像素 2×)也可行。对植被、树木这类过度绘制严重的场景,显著减少着色器调用和 G-buffer 带宽。

可见性缓冲

Burns 与 Hunt 的可见性缓冲 (visibility buffer) 每像素只存三角形 ID 和实例 ID。几何 pass 极快:不读纹理,只写两个 ID。所有三角形和顶点数据(位置、法线、颜色、材质等)放在全局缓冲中。

flowchart LR
  A["几何 pass: 写三角形 ID + 实例 ID"] --> B["着色 pass: 按 ID 取三角形顶点数据"]
  B --> C["像素视线与三角形求交得重心坐标"]
  C --> D["插值顶点属性, 逐像素执行顶点着色计算, 计算纹理梯度"]
  D --> E["按任意光源分类方案着色"]

如上图,平时频率更低的计算(如顶点着色器计算)也要逐像素执行,纹理梯度也从头计算而非插值。听起来昂贵,但符合"算力增长快于带宽"的趋势,以计算换取过度绘制造成的带宽损失。场景少于 64k 个网格、每个网格少于 64k 个三角形时,每个 ID 16 位,G-buffer 小到每像素 32 位;更大场景为 48 或 64 位。

变体与扩展:

  • Stachowiak 利用 GCN 架构在第一遍中低成本计算并存储重心坐标,代价是额外存储;好处是动画网格不必把变形后的顶点流出到缓冲供着色阶段再取(原方案的缺点,额外耗带宽)。但若需要到相机的距离,也必须在第一遍存下,之后无法重建。
  • Aaltonen 指出 MSAA 网格采样法可用于上述各方案,进一步降低平均内存;Schied 与 Dachsbacher 在可见性缓冲上利用 MSAA 降低高质量抗锯齿的内存和着色量。
  • Pettineo 指出无绑定纹理 (bindless) 让延迟纹理更容易实现;他的系统 G-buffer 较大(深度、材质 ID、深度梯度)。在 Sponza 上与分簇前向(含或不含 z-prepass)比较:关闭 MSAA 时延迟纹理始终更快,开 MSAA 后变慢;而多数游戏已因分辨率提高转向时间抗锯齿,MSAA 支持在实践中不那么重要。
  • Engel 指出 DirectX 12 / Vulkan 让可见性缓冲更有吸引力:计算着色器剔除三角形集合,ExecuteIndirect 生成只含未剔除三角形的等效索引缓冲。配合先进剔除系统,在 San Miguel 场景中可见性缓冲在所有分辨率和抗锯齿设置下都胜过延迟着色,且分辨率越高差距越大。Lauritzen 讨论了 GPU 需要演进以改善延迟环境下材质着色器的访问与处理。

deferred+

Doghramachi 与 Bucci 的延迟纹理系统在前期集成激进剔除:把上一帧深度降采样并重投影,得到当前帧每像素的保守剔除深度,用来测试视锥内所有网格包围体的遮挡(见 遮挡剔除)。注意若有 alpha 裁剪纹理,任何初始 pass(包括 z-prepass)都必须读取它,否则裁剪区域后面的物体会被错误遮挡。产出的 G-buffer 含深度、纹理坐标、切线空间、梯度和材质 ID,数量多于其他延迟纹理方案,但避免了不必要的纹理访问。在《杀出重围:人类分裂》的两个简化场景中比分簇前向更快,且 warp 利用率明显更好,小三角形问题更少,GPU 曲面细分表现更好;还能更高效地处理更多种材质。主要缺点与多数延迟方案相同:透明与抗锯齿。

取舍

方案每像素存储优点代价
虚拟延迟纹理64 位过度绘制极便宜,配合虚拟纹理需管理纹理图集;梯度靠邻居推算
可见性缓冲32~64 位几何 pass 最快,带宽最低着色阶段逐像素重做顶点工作与求交;动画网格需额外处理
deferred+较多剔除激进、材质灵活G-buffer 较大

GEA 的视角:可见性缓冲是"扩展的深度缓冲"(卷 II 11.5.2.1、11.6.8.6)

  • GEA 在讨论过度绘制时把可见性缓冲称为一种特殊的"扩展深度缓冲",作为 z 预通道之外的另一种解决办法(卷 II 11.5.2.1)。
  • 在 Nanite 一节中,它存每个像素的深度、物体 ID 和三角形 ID,把可见性问题与光照问题解耦:像深度预通道,但同时又是"廉价的 G-buffer",只保存足以在后续光照 pass 中查到材质的信息(卷 II 11.6.8.6)。这与本页「可见性缓冲」的描述一致,具体见 Nanite 虚拟化几何体 中的 GEA 部分。GEA 第 12 章还会进一步讨论 G-buffer 与可见性缓冲。

GEA 的视角:可见性缓冲(卷 II 12.5.12.2)

GEA 把三角形可见性缓冲看作 G-buffer 的一种变体:帧缓冲里的一个图像平面存"原始场景中哪个三角形贡献了这个像素",屏幕空间光照时据此查出每个三角形的完整材质描述。它通常更省内存,在高分辨率显示模式下尤其明显。GEA 推荐 Wolfgang Engel 关于可见性缓冲的论文(卷 II 12.5.12.2)。这与本页的描述一致,本页还讨论了 RTR4 中的延迟纹理、带宽与计算的权衡。

  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 第 11 章 11.5.2.1、11.6.8.6 节
  4. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 12 章 12.5.12.2 节

相关页面

图形学延迟着色Deferred Shading延迟着色先用一遍几何 pass 把所有可见表面的材质参数写入多张渲染目标(G-buffer),再以后处理方式对这些存储值逐光源计算光照,从而把"几何可见性"与"光照"彻底解耦,并把材质与光源分离。它避免了着色的过度绘制、简化了着色器管理、天然适合贴花,但 G-buffer 占用显存和带宽,且难以直接支持透明和 MSAA。本页也覆盖前向渲染下限制光源影响范围的基础手段与"光照预通道 (light prepass)"类混合方案。图形学分簇着色Clustered Shading分簇着色把整个视锥(而不只是屏幕平面)划分为三维单元——簇 (cluster),按簇建立光源列表。与依赖场景几何深度的分块着色不同,簇的划分与几何无关,可只由视图和光源计算,因此对相机位置的性能波动更小、对深度不连续更稳健,并为不透明、透明、体积物体提供统一的光照方案。它同样可配合前向或延迟着色,并衍生出 z-binning、光源树等更省内存的变体。本页还汇总了各类多光源方案的对比。图形学遮挡剔除Occlusion Culling遮挡剔除尽早剔除被其他物体挡住的物体,避免它们在 z-buffer 中被光栅化、深度比较甚至着色。本页覆盖遮挡剔除的分类与通用框架、GPU 遮挡查询、层次 Z 缓冲 (HZB) 及其在现代引擎中的简化变体(含两遍法、软件光栅化遮挡),以及在 CPU/GPU 上按物体—簇—三角形多粒度组合剔除并用间接绘制提交的剔除系统。图形学大场景渲染与虚拟纹理Large Scenes & Virtual Texturing当场景数据远大于内存(如主机只有 8 GB,而游戏世界有数百 GB)时,需要按需把数据流送进内存。本页讲三类技术:虚拟纹理(把巨大的 mipmap 链切成瓦片,只让可见瓦片驻留在显存,通过页表/间接纹理寻址)、纹理转码(磁盘上用高压缩比的可变码率格式,加载时转成 GPU 块压缩格式),以及按平面瓦片组织资产的通用流送。这些方法几乎总是与剔除和 LOD 配合使用;地形部分见 地形渲染。图形学顶点压缩与精度Vertex Compression & Precision网格数据像纹理一样可以压缩:传输用的整体压缩(Draco 等)一次性解码,渲染用的定长压缩让顶点着色器在 GPU 上逐顶点解码,从而降低内存、带宽并改善缓存。另一面是精度问题:大世界中单一坐标系会让远离原点的物体抖动,需要相对相机的变换或分段原点。图形学抗锯齿Antialiasing渲染本质上是采样,采样频率不足就会混叠(锯齿、闪烁的"萤火虫"、车轮倒转)。屏幕空间抗锯齿在每个像素取多个样本并加权求和:超采样最直接但最贵,MSAA 每像素只着色一次,时间抗锯齿 (TAA) 把样本分散到多帧,形态学方法 (FXAA/SMAA) 作为后处理重建边缘。没有一种方法在所有方面最好。图形学纹理过滤与 MipmapTexture Filtering & Mipmap纹理在屏幕上被放大时需要插值,被缩小时一个像素覆盖许多纹素,必须预先滤波才能避免混叠。放大用最近邻、双线性或双三次;缩小的主流方案是 mipmap + 三线性插值,斜视角下用各向异性过滤减少过度模糊。注意:过滤纹理值只在输入与着色结果线性相关时等价于过滤最终颜色。图形学渲染瓶颈定位与性能度量Bottleneck Location & Performance Measurement渲染管线中最慢的阶段(瓶颈)决定整体吞吐量。优化就是"找到瓶颈 → 优化到瓶颈转移 → 重复",并让非瓶颈阶段做到与瓶颈同样多的工作以换取画质。定位靠逐阶段增减负载的实验和性能工具;度量要用毫秒帧时间而不是 FPS。两条箴言:了解你的架构 (KNOW YOUR ARCHITECTURE);测量、测量、再测量。游戏数学相交测试基础与分离轴Intersection Test Fundamentals & Separating Axis相交测试判断两个对象是否相交(包含、边界相交或分离),有时还需要最近交点或穿透深度与方向,是碰撞检测、视锥剔除、拾取和光线追踪的基础。本页汇总 RTR4 第 22 章的通用工具:光线与曲面的表示、常见包围体定义(AABB、OBB、k-DOP、凸多面体、胶囊与菱形体)、分离轴测试 (SAT)、几何概率与表面积启发式 (SAH)、设计相交例程的经验法则,以及基于 GPU 的拾取。游戏开发 · UE5Nanite 虚拟化几何体Nanite Virtualized GeometryNanite 是 UE5 的虚拟化几何体 (Virtualized Geometry) 系统:导入时把网格切成分层的三角形簇 (Cluster),渲染时按相机视角逐簇选择细节层次并无缝拼接,按需从磁盘流送,并在绕过传统绘制调用 (Draw Call) 的独立通道中渲染,使帧预算不再受多边形数、绘制调用和网格内存约束。图形学对象空间与纹理空间着色Object- & Texture-Space Shading对象空间/纹理空间着色把着色计算的频率与几何采样(光栅化)的频率解耦:在物体的参数化(纹理图表)上计算着色并存入纹理,最终光栅化时只查表。思想源自 Pixar 的 Reyes 离线渲染器的微多边形着色。它能消除 quad 过度着色、按屏幕覆盖率控制着色量、在帧间复用着色结果,甚至让着色以低于光栅化的帧率异步运行;代价是物体必须有唯一的 uv 图表、先着色后遮挡带来浪费等。图形学深度缓冲Z-Buffer深度缓冲是几乎所有图形硬件用来解决可见性的算法:为每个像素存一个当前最近图元的深度值,新片元更近才写入颜色和深度。它简单、和图元数量成线性关系、允许大多数图元以任意顺序绘制,但不能直接处理半透明。图形学像素着色器Pixel Shader像素着色器(OpenGL 里叫片元着色器)对光栅化产生的每个片元运行,用插值后的顶点数据算出颜色,也可以输出不透明度、修改深度或直接丢弃片元。多渲染目标让它一次输出多组数据,催生了延迟着色。它通常只能写自己所在的像素,但能通过 2×2 quad 拿到相邻像素的导数。

输入关键词开始搜索

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