中EN
概念页

遮挡剔除

Occlusion Culling

遮挡剔除尽早剔除被其他物体挡住的物体,避免它们在 z-buffer 中被光栅化、深度比较甚至着色。本页覆盖遮挡剔除的分类与通用框架、GPU 遮挡查询、层次 Z 缓冲 (HZB) 及其在现代引擎中的简化变体(含两遍法、软件光栅化遮挡),以及在 CPU/GPU 上按物体—簇—三角形多粒度组合剔除并用间接绘制提交的剔除系统。

为什么需要(19.7 节)

z-buffer 能正确解决可见性,但它是蛮力的。视线方向排成一列的 10 个球,最终只看到 1 个,中间像素的深度复杂度为 10:后到前绘制会有 9 次多余的像素着色;即使前到后绘制,10 个球的三角形仍要全部光栅化并做深度比较。雨林、发动机、城市、摩天楼内部这类密集场景都是如此。背面剔除可以看作最简单的遮挡剔除。

分类与通用框架

  • 基于点 vs 基于单元:基于点是从单一视点判断;基于单元针对一个区域(盒或球)内所有视点,物体必须从单元内任何一点都看不见。后者算一次可在视点留在单元内的若干帧复用,但计算更贵,常作为预处理。二者类似点光源与面光源:物体不可见相当于位于本影中。
  • 图像空间 / 物体空间 / 光线空间:实时图形中图像空间算法最常用。

通用算法(Zhang)维护遮挡表示 OR 和潜在遮挡物集合 P:

flowchart TD
  A["取下一个通过视锥剔除的物体 g"] --> B{isOccluded g, OR}
  B -- "是" --> C["跳过"]
  B -- "否" --> D["渲染 g 并加入 P"]
  D --> E{"P 足够大?"}
  E -- "是" --> F["把 P 合并进 OR, 清空 P"]
  E -- "否" --> A
  F --> A
  C --> A

如上图,被判为遮挡的物体直接跳过,未被遮挡的物体渲染后成为新的遮挡物。性能强烈依赖绘制顺序:先画车引擎盖,发动机很可能被剔除;先画发动机则什么都剔不掉,因此粗略的前到后排序收益显著。小物体也可能是好遮挡物——足够近时一个火柴盒能挡住金门大桥。

遮挡查询(19.7.1 节)

GPU 的特殊渲染模式:光栅化一组三角形(通常是复杂物体的 BV,如盒或 k-DOP),与当前 z-buffer 比较,返回可见像素数 nn,但不写任何颜色和深度。

  • n=0n=0 还需保证视锥可见近平面的任何部分都不在 BV 内,才能安全剔除;nn 小于阈值时可以近似丢弃(以质量换速度),nn 也可用来选择更低的 LOD。
  • 只需布尔结果时可用 ANY_SAMPLES_PASSED(OpenGL 3.3 / DirectX 11 起),一有片元通过就能提前结束;OpenGL 4.3 的 ANY_SAMPLES_PASSED_CONSERVATIVE 允许只与粗深度缓冲比较,只要保守即可。
  • 延迟很长,期间可渲染成百上千个三角形,所以只在包围盒内物体很多、遮挡很多时划算。查询模型是异步的:CPU 发出任意多个查询,定期检查结果队列而不停顿。谓词/条件渲染把查询与对应绘制调用一起提交,GPU 仅在查询可见时执行该绘制,大大提高了实用性。
  • 调度:被遮挡的物体每帧都测,可见的物体往往保持可见,可以少测(按多帧统计调整频率);无条件渲染时可以批量合并查询、用多个小盒代替一个大盒、对之前可见的物体做时间抖动采样调度。
  • 难点:如果一切都可见,遮挡算法只增加开销;要快速察觉算法无效并收手;视锥内最先绘制的物体必然可见,对它们查询是浪费;何时以何种顺序测试很难决定。

层次 Z 缓冲 HZB(19.7.2 节)

原始算法把场景放进八叉树,把 z-buffer 维护为图像金字塔 z-pyramid:最细层就是 z-buffer,其他层每个值是下一层对应 2×22\times2 窗口中的最远 z。z-buffer 被改写时向上传播。按粗略前到后遍历八叉树,把节点包围盒在能包住其投影的最粗 z-pyramid 单元上测试,若盒的最近深度 znearz_{near} 比该单元更远则被遮挡,否则下降到更细层直到判定遮挡或到达底层(可见);可见节点继续向下遍历并把几何渲染进 HZB,供后续测试使用。完整 HZB 如今已不用,但它是 GPU 硬件 z-culling 的基础,也启发了大量基于计算着色器或 CPU 软件光栅化的自定义剔除。

现代简化流程(大多数实现不用八叉树,也不在渲染后更新 z-pyramid,因为太贵):

  1. 用某种遮挡物表示生成完整 z-pyramid。
  2. 把物体 BV 投影到屏幕,用投影后最长边 ll(像素)选择 mip 层:
λ=min⁡(⌈log⁡2(max⁡(l,1))⌉,  n−1)\lambda=\min\left(\left\lceil \log_2(\max(l,1)) \right\rceil,\; n-1\right)

其中 nn 是 z-pyramid 的层数,max 防止负层级,min 防止越界。(原文取整符号在提取中丢失;书中说明该式选择使投影 BV 至多覆盖 2×22\times2 个深度值的最低整数层,此处按向上取整写出。)这样每次测试最多读 4 个深度值,成本可预测;而且大物体本就更可能可见,没必要读更多。 3. 计算 BV 的最小深度 zminz_{min}(视空间 AABB 直接取最小深度;OBB 把顶点投影到视线方向取最小;球取 c−rc/∥c∥\mathbf{c}-r\mathbf{c}/\lVert\mathbf{c}\rVert),若它比这至多 4 个深度值都大则遮挡。相机在 BV 内时直接渲染。可选地再维护一个存最小深度的金字塔:BV 的 zmaxz_{max} 比其中所有值都小则一定可见;两者重叠时再到更细层测试。2×22\times2 比较类似百分比渐近过滤,可直接用带比较的双线性采样实现。

遮挡物来源:最近的 n 个"最佳"遮挡物、美术制作的简化遮挡体、上一帧可见物体统计,或直接用上一帧 z-buffer(不保守,快速运动时物体会突然冒出)。Haar 与 Aaltonen 把最佳遮挡物与上一帧 1/16 分辨率重投影深度结合,用 GPU 生成金字塔,有的实现借助 AMD GCN 的 HTILE 加速。

两遍法(Haar 与 Aaltonen;Kubisch 与 Tavenrath 类似)保证所有可见物体都被渲染:

flowchart LR
  A["用上一帧 z-pyramid 测试所有物体"] --> B["渲染判为可见的物体"]
  B --> C["由本帧深度重建 z-pyramid"]
  C --> D["重测第一遍被剔除的物体"]
  D --> E["渲染未被剔除者"]

即使相机或物体快速运动,结果也完全正确。

其他变体:

  • Doghramachi 与 Bucci:把被遮挡物的 OBB 光栅化到降采样并重投影的上一帧深度上,强制 early-z,可见片元按物体 ID 在缓冲中标记可见,比 mip 层测试剔除率更高。
  • Collin:256×144256\times144 浮点 z-buffer(非层次)在 CPU 或 PS3 的 SPU 上用 SIMD 软件光栅化美术遮挡体,测试物体屏幕 AABB 的 zminz_{min},只把幸存物体发给 GPU;分辨率低于帧缓冲,所以不保守。Wihlidal 建议再用它的 zmaxz_{max} 预填 GPU 的 HiZ(如 HTILE),或生成计算剔除用的 z-pyramid。
  • 遮罩层次深度缓冲 MHDB(Hasselgren 等):每个 8×48\times4 瓦片每像素 1 位掩码加两个 zmaxz_{max},共每像素 3 位;两个深度分别给前景和背景,能更好处理深度不连续。保守、可做 zmaxz_{max} 剔除,每个三角形都更新,软件光栅化很快;可配合 AABB 树分层测试,或用堆按前到后遍历整个场景。开源代码针对 AVX2 深度优化。
  • 中间件:Umbra 等专用剔除框架已集成进多款引擎。

剔除系统(19.8 节)

现代系统在多个粒度上组合剔除,有的完全在 GPU 计算着色器中进行,有的 CPU 粗剔、GPU 细剔。

flowchart LR
  A["物体/实例剔除"] --> B["簇/块剔除"]
  B --> C["三角形剔除"]
  C --> D["压缩幸存三角形列表"]
  D --> E["间接绘制"]
  • 簇 (cluster/chunk) 是物体三角形的子集,例如 64 顶点的三角形带或 256 个三角形一组。物体级可用小三角形、细节、视锥、遮挡剔除;簇更小、更易被剔除,可用细节、视锥、成簇背面、遮挡剔除。
  • 三角形级:除以 w 后与 ±1\pm1 比较的视锥剔除、背面、退化三角形、小三角形,可能还有遮挡。幸存者压缩成紧凑列表,计算着色器把三角形数写入 GPU 缓冲,用间接绘制(OpenGL 的 multi-draw indirect、DirectX 的 execute indirect)让 GPU 给自己下绘制命令,无需 CPU 往返。
  • 代表工作:Shopf 等人把角色 AI 放在 GPU 上,位置只存在显存中,因此用计算着色器做剔除与 LOD,影响了后续大多数系统;《刺客信条:大革命》(Haar 与 Aaltonen);Frostbite(Wihlidal);配合可见性缓冲的系统(Engel);大量零件的大模型渲染(Kubisch 与 Tavenrath,用几何着色器生成包围盒可见面再靠 early-z 剔除)。
  • 最佳组合尚无定论,取决于目标架构和内容。

取舍

方法优点缺点
硬件遮挡查询精确、易用,可条件渲染延迟长,结果常需下一帧使用
HZB 计算剔除全 GPU、成本可预测,可配合间接绘制依赖遮挡物质量;用上一帧深度需两遍法保证正确
CPU 软件光栅化不占 GPU,早剔除减少提交低分辨率不保守,占 CPU
MHDB保守、逐三角形更新实现复杂,依赖 SIMD

GEA 的视角:PVS 与 HiZ(卷 II 11.5.1.3、11.6.8.6)

  • 何时值得做:地面视角的拥挤环境中物体互相遮挡很多,遮挡剔除极其重要;场景稀疏或从高处俯视时遮挡少,剔除的开销可能超过收益(卷 II 11.5.1.3)。
  • 潜在可见集 (PVS):对任意相机位置列出可能可见的物体,宁可多列不可见的,也不漏掉会出现在画面中的。常见实现是把关卡切成区域,每个区域附一张"在此区域内能看到哪些区域"的列表。可以由美术或策划手工指定,更常见的是离线工具根据用户划定的区域自动生成:在区域内随机分布的视点上渲染场景,每个区域的几何用不同颜色编码,扫描帧缓冲统计出现的颜色即得可见区域列表。自动工具不完美,通常允许手动放置测试视点,或手动指定某区域 PVS 中必须包含或排除的区域。
  • HiZ 与两遍法:GEA 在 Nanite 一节介绍了层次 Z 缓冲的构建(每级存下层四像素的最大深度)、按簇屏幕范围选 mip 级的单次采样测试,以及"先重画上一帧可见簇建 HZB、再测其余"的两遍法(卷 II 11.6.8.6)。这与本页「层次 Z 缓冲 HZB」和「两遍法」一致,细节见 Nanite 虚拟化几何体 中的 GEA 部分。
  • 入口与反入口见 剔除技术 中的 GEA 部分。
  1. realtime_rendering_4ed.pdf 第 19 章 Acceleration Algorithms
  2. Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 11 章 11.5.1.3、11.6.8.6 节

相关页面

图形学剔除技术Culling Techniques剔除 (culling) 是在渲染前尽快去掉对最终图像没有贡献的部分。本页讲几何类剔除:背面剔除(含成簇背面剔除与法线锥)、视锥剔除(层次化、平面掩码)、室内场景的入口剔除,以及牺牲质量换速度的细节剔除和小三角形剔除。更复杂的遮挡剔除见 遮挡剔除。图形学空间数据结构Spatial Data Structures空间数据结构把几何体按 n 维空间组织起来,通常是层次化的树,使"几何体是否重叠"一类查询从 O(n) 降到大约 O(\log n)。常见类型有包围体层次 (BVH)、BSP 树(轴对齐的 k-d 树与多边形对齐两种)、四叉树/八叉树(含松散八叉树),以及更偏向组织模型关系的场景图。它们是剔除、光线求交、碰撞检测等加速算法的基础。图形学深度缓冲Z-Buffer深度缓冲是几乎所有图形硬件用来解决可见性的算法:为每个像素存一个当前最近图元的深度值,新片元更近才写入颜色和深度。它简单、和图元数量成线性关系、允许大多数图元以任意顺序绘制,但不能直接处理半透明。图形学像素与帧缓冲优化Pixel & Framebuffer Optimization需要着色的像素通常远多于顶点,所以像素处理优化往往最划算。核心手段:保证占用率以隐藏纹理延迟、按距离切换着色器 LOD、利用 early-z 并通过从前往后排序或 z-prepass 减少过度绘制、缩小帧缓冲每像素存储(色度子采样、YCoCg 棋盘),以及只在需要时开启混合、避免 GPU 回读。几何与光栅化阶段的常用优化也一并列出。图形学计算着色器Compute Shader计算着色器是 DirectX 11 引入的一种 GPU 计算方式:它不固定在图形管线的某个位置,但由图形 API 调用,和其他着色器共用统一着色器核心。它暴露了线程组和组内共享内存,最大的优势是能直接处理 GPU 上生成的数据,不用来回传给 CPU。图形学软阴影 PCF 与 PCSSSoft Shadows with PCF & PCSS百分比渐近过滤 (PCF) 在阴影贴图上取多个样本,分别与表面深度比较后混合结果,得到伪软阴影,但半影宽度恒定。PCSS 先搜索附近遮挡体的平均深度,再据此决定过滤宽度,从而在接触处硬、远处软(接触硬化)。图形学细节层次Level of Detail细节层次 (LOD) 在物体对图像贡献变小时改用更简单的表示。LOD 系统由三部分组成:生成(简化或手工制作多个版本)、选择(按距离、投影面积等收益函数挑选)、切换(尽量减少跳变 popping)。LOD 主要减少顶点处理,也通过减少 quad 过度着色降低像素开销;进一步还可在预算约束下全局选择 LOD,实现时间关键(恒定帧率)渲染。图形学绘制调用与状态切换优化Draw Calls & State Change Optimization调用图形 API 的开销主要在 CPU 端的驱动里:状态切换昂贵,每次绘制调用有固定开销,大量小批次会让 GPU"饿死"。对策是:合理放置缓冲;按状态代价排序分组;共享纹理和着色器;合并网格和实例化以减少调用;并用一个整数排序键同时兼顾状态分组与前后排序。图形学延迟纹理与可见性缓冲Deferred Texturing & Visibility Buffer延迟着色避免了着色的过度绘制,但生成 G-buffer 时仍有过度绘制:先画的物体读了大量纹理,被后画的物体挡住后这些带宽全部浪费。延迟纹理只用一遍几何 pass、存极少的数据(纹理坐标与切线基,或仅三角形与实例 ID),直到着色时才读纹理。由于 GPU 算力增长快于带宽,让瓶颈落在计算而非缓冲访问被视为面向未来的做法。图形学硬件深度剔除与纹理单元Hardware Depth Culling & Texture UnitsGPU 的深度管线先在瓦片级用 HiZ 单元做 zmax/zmin 粗剔除,再逐采样做 early-z 深度测试以免执行被遮挡片元的像素着色器,必要时退回到着色后的 late depth test;深度缓冲同样有瓦片压缩与快速清除。纹理单元以固定功能硬件完成寻址、过滤、钳位与解压(比软件快可达 40 倍),按 quad 有限差分求导数以选择 LOD,并依靠瓦片化/Morton 交织存储和纹理缓存提高局部性。图形学GPU 计算调度与占用率GPU Compute Scheduling & OccupancyGPU 用大量统一的 ALU 以 SIMD/SIMT 方式锁步执行着色程序,ALU 与寄存器文件、L1、本地数据存储、纹理单元等组成多处理器 (MP),由硬件 warp 调度器零开销地切换 warp 以隐藏纹理和内存访问的长延迟。能同时驻留的 warp 数受寄存器等资源限制,用占用率衡量;占用率低会妨碍延迟隐藏,但过高也可能抖动缓存。本页还讨论像素按 quad 调度和 GPU→CPU 回读延迟。游戏开发 · UE5Nanite 虚拟化几何体Nanite Virtualized GeometryNanite 是 UE5 的虚拟化几何体 (Virtualized Geometry) 系统:导入时把网格切成分层的三角形簇 (Cluster),渲染时按相机视角逐簇选择细节层次并无缝拼接,按需从磁盘流送,并在绕过传统绘制调用 (Draw Call) 的独立通道中渲染,使帧预算不再受多边形数、绘制调用和网格内存约束。游戏开发 · 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、压缩、分块架构)理解这些手段为何有效。各结论的细节与出处见所链接的概念页。图形学图形栈与渲染引擎架构Graphics Stack & Rendering Engine Architecture渲染引擎要解决的"渲染问题"是:给定由场景元素、虚拟光源和虚拟相机组成的虚拟世界,生成相机看到的二维彩色图像。GEA 把它拆成可见性问题和光照问题,按解法把引擎分为光线追踪、深度缓冲光栅化、辐射度和混合四类;光栅化引擎通常采用立即模式的两层结构:下层是图形管线,上层是负责剔除、提交几何和设置着色器参数的应用层。本页讲这套整体架构,管线内部见 渲染管线。游戏开发三维音频渲染3D Audio Rendering3D 音频渲染引擎要尽可能可信地重现"玩家若真在游戏世界里会听到什么"。它的输入是世界里大量的 3D 声音,输出是少数几路扬声器声道;主要任务是合成、空间化(距离衰减 + 声像定位)、声学建模(混响、遮挡、衍射)、多普勒和混音。GEA 给出了恒功率声像律、聚焦角、混响区域交叉混合、遮挡/阻挡/排除的分析方法,以及顽皮狗《最后生还者》的随机传播建模和声音门户(GEA4 卷 II 15.4)。

输入关键词开始搜索

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