news 2026/5/1 4:10:57

看不见的战争 —— 遮挡剔除技术的演进与终极形态

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
看不见的战争 —— 遮挡剔除技术的演进与终极形态

如果说 LOD 是为了解决“太远看不清”的问题,那么遮挡剔除(Occlusion Culling)就是为了解决“被挡住看不见”的问题。在复杂场景中(如城市、森林),摄像机视锥体(Frustum)内的物体可能只有 10% 是真正可见的,其余 90% 都被前面的物体遮挡。

如果不剔除这些物体,GPU 依然会执行顶点着色器(VS),并在光栅化阶段进行昂贵的深度测试(Z-Test)。对于 Cluster 架构而言,无效的计算是不可容忍的。

常见的遮挡剔除方法及其局限性

vk_lod_clusters这种现代方案出现之前,业界主要使用以下几种方法,它们各有痛点:

1. 预计算可见性 (PVS - Potentially Visible Sets)

  • 原理:在开发阶段将场景划分为格子(Cells),预先计算好“在格子 A 能看到哪些物体”,并将列表烘焙到数据中。经典游戏如《Quake》和《CS 1.6》大量使用。

  • 局限:

    • 仅限静态场景:墙壁塌了、门开了,PVS 就失效了。

    • 存储压力:开放世界的 PVS 数据量巨大。

    • 构建时间长:每次修改地图都要重新烘焙几个小时。

2. 硬件遮挡查询 (Hardware Occlusion Queries)

  • 原理:CPU 告诉 GPU:“帮我画个不可见的包围盒,告诉我画了几个像素?”。如果 GPU 返回 0,说明物体被遮挡,CPU 就不提交该物体的绘制命令。

  • 局限:

    • CPU-GPU 延迟(Latency):CPU 必须等待 GPU 返回结果才能决定是否绘制。这会打断流水线,产生“气泡(Bubbles)”。

    • “上一帧”策略的闪烁:为了不等待,常使用上一帧的结果,但这会导致新出现的物体闪烁(Pop-in)。

3. 软件遮挡剔除 (Software Occlusion Culling)

  • 原理:在 CPU 端手写一个简易光栅化器(如 Intel 提出的方案),将粗糙的遮挡物绘制到 CPU 内存的深度缓冲中,然后直接在 CPU 端判断可见性。

  • 局限:

    • CPU 负载高:现在的游戏 CPU 本来就忙着处理物理和 AI,还要分摊光栅化任务,容易成为瓶颈。


vk_lod_clusters 的核武器:GPU-Driven Hi-Z Culling

vk_lod_clusters(以及 Nanite)采用的是目前最先进的GPU 驱动的两阶段剔除(Two-Phase Occlusion Culling),配合Hi-Z(Hierarchical Z-Buffer)技术。

这种方法完全运行在 GPU 的 Compute Shader 上,无需 CPU 介入,且完美解决了“延迟”和“闪烁”问题。

2.1 什么是 Hi-Z (Hierarchical Z-Buffer)?

普通的深度缓冲(Z-Buffer)是一张全分辨率的纹理。Hi-Z 是一个深度纹理的金字塔(Mipmap Chain)。

  • Level 0:原始深度图。

  • Level 1:将 Level 0 每个像素取最远深度(Max Depth)(对于反向 Z-Buffer 则是取 Min)。

  • Level N:以此类推,直到

核心优势:

当我们要判断一个 Cluster 的包围盒是否被遮挡时,不需要遍历全屏幕的深度像素。我们只需要根据包围盒在屏幕上的大小,选择一个合适的 Mipmap 层级,使得包围盒在该层级只覆盖约 4 个像素。读取这 4 个值,就能知道该区域的“最保守遮挡深度”。

公式逻辑:

如果(假设 0 是近,1 是远),说明 Cluster 比前面所有的遮挡物都要远,即被遮挡

2.2 两阶段剔除算法 (The Two-Phase Algorithm)

这是vk_lod_clusters避免物体闪烁的精髓。因为我们在渲染当前帧时,还没有当前帧的深度图(还没画呢),所以必须分两步走:

第一阶段:主剔除 (Main Pass / Occlusion Pass 1)
  1. 输入:上一帧生成的 Hi-Z Buffer(经过重投影 Reprojection 处理,以适应相机移动)。

  2. 执行:Compute Shader 并行检查所有 Cluster 的包围盒。

  3. 判断:

    • 如果 Cluster 被上一帧的 Hi-Z 遮挡 $\rightarrow$标记为不可见(暂时不画)。

    • 如果 Cluster 可见 $\rightarrow$立即加入绘制列表,并标记为“Pass 1 已绘制”。

  4. 渲染:GPU 绘制这些通过测试的 Cluster,生成当前帧的 Depth Buffer

  5. 构建 Hi-Z:基于当前帧的 Depth Buffer,生成当前帧的 Hi-Z

问题:上一帧被遮挡的物体,这一帧可能因为遮挡物移开而变得可见。但在 Pass 1 中它被错误地剔除了(False Negative)。这会导致物体消失或闪烁。

第二阶段:修正剔除 (Post Pass / Correction Pass 2)
  1. 输入:当前帧刚刚生成的最新 Hi-Z Buffer。

  2. 执行:再次检查在 Pass 1 中被判定为不可见的那些 Cluster。

  3. 判断:

    • 利用最新的 Hi-Z 再次测试。

    • 如果这次测试发现它其实是可见的(即刚才 Pass 1 误判了) $\rightarrow$加入补充绘制列表

  4. 补画:绘制这些漏网之鱼。

2.3 为什么这适合 Cluster?

这种两阶段剔除在传统的 Object 级别渲染中开销很大(因为 Draw Call 多)。但在 Cluster 架构下:

  • 粒度完美:Cluster 的包围盒很小,遮挡测试非常精准。

  • 并行度高:几百万个 Cluster 的遮挡测试可以在 Compute Shader 中瞬间完成。

  • 零 CPU 开销:整个过程(剔除 $\rightarrow$ 生成 Indirect Draw Arguments $\rightarrow$ 绘制)全在 GPU 上通过 Buffer 传递,CPU 甚至不知道哪些 Cluster 被画出来了。


代码实现的逻辑流 (伪代码)

为了让读者更直观地理解,我们可以将其逻辑抽象为以下 Compute Shader 伪代码:

// Compute Shader: process_clusters.comp void main() { uint clusterID = gl_GlobalInvocationID.x; BoundingBox bounds = GetClusterBounds(clusterID); // 1. 视锥剔除 (Frustum Culling) if (!IsVisibleInFrustum(bounds)) return; // 2. 计算屏幕空间的包围盒大小 vec4 screenRect = ProjectToScreen(bounds); // 3. 选择 Hi-Z Mipmap 层级 // 确保包围盒在 Mipmap 上大约占 2x2 或 4x4 像素 float mipLevel = CalculateMipLevel(screenRect); // 4. 采样 Hi-Z 深度 // 这里的 sampler 是 "上一帧" (Pass 1) 或 "当前帧" (Pass 2) float occlusionDepth = textureLod(hiZTexture, screenRect.center, mipLevel).r; // 5. 深度比较 float clusterDepth = bounds.nearestDepth; bool isOccluded = (clusterDepth > occlusionDepth); // 假设远是大值 if (!isOccluded) { // 原子操作:将 Cluster ID 写入绘制缓冲 uint index = atomicAdd(drawCountBuffer, 1); visibleClusters[index] = clusterID; } }

四、 总结

vk_lod_clusters使用的 Hi-Z 两阶段剔除方案,是目前实时渲染领域解决“过绘(Overdraw)”的终极方案之一。

它不再依赖美术手动放置遮挡板,不再依赖离线烘焙。它利用 Cluster 的微小粒度,像手术刀一样精准地剔除了每一块不可见的几何体,保证了无论场景多么复杂,显卡只渲染最终用户看得到的那一层像素。这就是为什么 Cluster 架构能支撑十亿级多边形的核心原因之一。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 15:53:24

git gui设置github sshkey

要在 Git GUI 中生成 SSH 密钥,请按以下步骤操作: 方法 1:使用 Git GUI 的密钥生成工具 步骤:打开 Git GUI git gui进入帮助菜单 菜单栏点击 Help选择 Show SSH Key生成新密钥 点击 Generate Key选择密钥类型(RSA 2048…

作者头像 李华
网站建设 2026/4/29 1:44:20

RAG 检索增强生成实战:基于 Spring AI 构建本地知识库 AI 问答系统

RAG(检索增强生成)作为融合信息检索与大语言模型文本生成的核心技术,能够通过外部知识库动态补充实时、精准的专属信息,从根源上提升大语言模型回答的准确性、时效性,还能有效抑制传统 LLM 的 “幻觉” 问题、解决模型…

作者头像 李华
网站建设 2026/4/13 10:52:07

2026年版|程序员必看(建议收藏):大模型引发职业洗牌,小白入门老程序员转型攻略

2026年,浏览各大招聘平台不难发现一个核心变化:过去技术岗位招聘中,除了重点考察“能否独立搭建常规系统框架”“是否具备数据库存储优化能力”等核心硬技能,如今几乎所有技术岗都悄悄新增了“拥有大模型实际应用经验者优先”这一…

作者头像 李华
网站建设 2026/4/19 7:15:04

【计算机毕业设计案例】基于ssm的体育馆管理员工信息管理,器材信息管理系统的设计与实现基于ssm的体育器材管理系统设计与实现(程序+文档+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/4/17 1:11:04

【深度收藏】AI Agent从零构建:大语言模型到智能体实现的完整路径

文章详细解析了构建AI Agent的四大核心技术组件:智能内核(大语言模型、上下文窗口、提示工程)、知识扩展(向量数据库、Embeddings、RAG)、行动逻辑(LangChain、LangGraph、MCP)以及各组件协同工作的完整流程。这些技术共同构成了从简单对话机器人升级为全能AI Agent…

作者头像 李华
网站建设 2026/4/24 17:09:53

P6KE13CA双向TVS瞬态抑制二极管:600W功率13V电压车载工控专用防护

双向P6KE13CAtvs瞬态电压抑制二极管 P6KE13CA双向 TVS瞬态抑制二极管 二极管产品已经跟我们的生活有着密不可分的联系了, TVS瞬态抑制二极管,是一种高效能保护二极管,产品体积小、功率大、响应快等诸多优点,产品应用广泛 TVS瞬态…

作者头像 李华