可见性剔除:遮挡、视锥与 Portal 的层级设计 可见性剔除遮挡、视锥与 Portal 的层级设计一、看不见的就不该画实时渲染的其一是条铁律是不可见的物体不渲染。一个开放场景里可能有十万物件但玩家同一时刻只能看到其中一小部分。把全部物件都送进管线是带宽与顶点处理的双重浪费。可见性剔除Visibility Culling就是一套把看不见的在最早阶段剔掉的层级体系是大规模场景帧率的基石。剔除不是单一技术而是分层递进先在最粗粒度砍掉整个区域再逐层细化到单个物体。每一层都面向不同规模的浪费组合使用才能把绘制调用压到最低。二、层级剔除的数据流典型的层级剔除从粗到细依次为视锥剔除、遮挡剔除、Portal 剔除。这一过程如同一个漏斗从场景全部物件开始逐级过滤直至提交绘制的可见集。视锥剔除最简单不在相机视野四棱锥内的直接丢弃遮挡剔除更聪明被前景大物体完全挡住的也被丢弃。Portal 剔除面向室内通过门洞Portal判断哪些房间可能可见房间外的直接跳过。三层漏斗逐级收窄可见集。三、生产级剔除查询与可见集构建实现下面是一段 C 示例展示如何用八叉树做视锥剔除并把可见集交给绘制。#includevector#includecmathstructAABB{floatminx,miny,minz,maxx,maxy,maxz;};structFrustumPlanes{floatp[6][4];};// 6 个平面: axbyczd// 球体与平面的有符号距离0 表示在背面staticinlinefloatDistToPlane(constfloatp[4],floatx,floaty,floatz){returnp[0]*xp[1]*yp[2]*zp[3];}// 用包围球做保守剔除球完全在任一平面背面则剔除boolIsVisible(constFrustumPlanesf,floatcx,floatcy,floatcz,floatr){for(inti0;i6;i){if(DistToPlane(f.p[i],cx,cy,cz)-r)returnfalse;// 保守宁可多画不可误剔}returntrue;}classCuller{public:std::vectorintCull(constFrustumPlanesf,conststd::vectorAABBboxes){std::vectorintvis;vis.reserve(boxes.size()/4);for(inti0;i(int)boxes.size();i){autobboxes[i];floatcx(b.minxb.maxx)*0.5f,cy(b.minyb.maxy)*0.5f,cz(b.minzb.maxz)*0.5f;floatrstd::sqrtf((b.maxx-b.minx)*(b.maxx-b.minx)(b.maxy-b.miny)*(b.maxy-b.miny)(b.maxz-b.minz)*(b.maxz-b.minz))*0.5f;if(IsVisible(f,cx,cy,cz,r))vis.push_back(i);}returnvis;// 返回可见索引集交由绘制提交}};这段代码的关键契约剔除必须保守——用包围球做测试宁可多画不可误剔。一旦错误剔除了本应可见的物体玩家会看到物体凭空消失比多画几帧更不可接受。生产环境应在八叉树或 BVH 上做层级剔除先砍整棵子树再细化到叶避免逐个物体裸测包围体更新需在物体移动时及时重算否则剔除会基于过期包围盒失效。在工程落地中遮挡剔除常采用软硬结合的策略。硬件遮挡查询适合GPU密集型场景但对室内复杂结构大多力不从心。此时需要软件遮挡体或预计算遮挡信息来补足。门户剔除则专门针对房间与走廊的连通关系玩家未穿过门就绝不加载门外内容对室内关卡收益极高。近年GPU驱动剔除把可见性判断下沉到绘制命令本身由GPU决定哪些绘制调用真正执行。进一步削减了CPU端的剔除开销与提交负担。四、保守误剔、遮挡精度与 CPU 开销的代价剔除的最大风险是误剔遮挡剔除若用不精确的遮挡体如用粗糙的盒代替真实遮挡物可能把本可见的物体判为被挡。导致穿帮。因此遮挡剔除常需保守的遮挡体或硬件遮挡查询GPU 回读但硬件查询本身有延迟与带宽成本需权衡。Portal 剔除依赖手工放置的门洞对自动化大世界不友好且 Portal 维护是额外美术工作量。CPU 侧剔除本身也有开销每帧遍历场景做可见性测试物件极多时这部分 CPU 时间不可忽略。需借助空间索引八叉树、BVH把复杂度从 O(N) 降到接近 O(log N)。收尾是过度剔除导致远处弹出的问题剔除太激进物件在转入视野瞬间才加载会有明显 pop-in需用淡入或预加载缓冲。所以落地建议剔除必须保守、用空间索引加速、遮挡用保守体或硬件查询Portal 配合手工放置远处用预加载缓冲防 pop-in。五、总结可见性剔除通过视锥、遮挡、Portal 的层级漏斗把不可见物体在最早期剔除是大规模场景帧率的基石。其风险是保守不足导致的误剔穿帮、遮挡精度与硬件查询成本的权衡、以及 CPU 侧测试的复杂度。工程落地须坚持保守剔除宁可多画借助八叉树或 BVH 把测试复杂度降到对数级遮挡剔除用保守遮挡体或硬件查询。并用预加载缓冲抑制远处 pop-in。包围体须在物体移动时及时更新避免基于过期数据失效。