游戏开发丨游戏中的遮挡剔除/Occlusion Culling
游戏中的剔除分为很多个级别,比如背面剔除、视锥剔除、遮挡剔除,EarlyZ,Z-Cull等等。
在这里面,遮挡剔除是最难以实现的,也是变化最丰富的,这里就来小结下游戏中常用来实现遮挡剔除的方式。
基于CPU的方式:
1.基于软光栅/Software Occlusion
这种方式需要手动标记好大型的用来遮挡的物体,在运行时,将遮挡物的包围盒(或最高LOD级别的模型)软光栅到CPU内存中的z-buffer上,然后根据z-buffer中的深度信息,根据需要剔除物体的包围盒,实时计算遮挡信息。
这种方式缺点是对CPU端压力很大,优点是非常灵活。
相对前面两种方案,软光栅剔除提供了非常大的灵活性,支持完全可变/任意大小的场景,适用于流式关卡/大世界中的应用。
相对GPU实现的遮挡剔除,这种方案完全不用担心硬件兼容问题。
2.Portal-Culling
这种方式也是将场景划分成Cell,不同的是,烘焙时保存的是每两个相邻Cell之间的连通性。
这样,在运行时,根据摄影机所在的位置的Cell和观察方向,就可以根据Cell间的连通性信息,快速计算出目标物体是否处于可见范围内。
相对上面完全的预计算,这种方式的优点就是可以剔除动态物体,同时提供了些许的静态遮挡物体变化的灵活性。比如有扇可以开关的门,当门被打开后,就可以将门两侧的Cell的连通打开。
3.预计算可见性/Precomputed Visibility
这种方式比较简单,就是先将场景划分成一个个Cell,让后对于每个Cell区域,预计算出摄影机在这个Cell范围内时,所有可能看到的物体,并将信息保存下来,这样在运行时就可以直接查表来得到所有静态物体的可见信息,运行时开销几乎为0。
基于GPU实现的剔除方案:
4. 遮挡查询/Occlusion Query
Occlusion Query首先使用一个简单的depth-only的pass将深度写入到z-buffer中,然后使用物体的包围盒传入到GPU进行遮挡测试,如果测试发现所有像素都被遮挡,说明这个物体是被遮挡的物体,否则的话认为是可见的。
OpenGL中的查询方式为Query Object - OpenGL Wiki。
DirectX中的查询方式为docs.microsoft.com/en-u。
由于从GPU回读数据到CPU通常很慢,因此通常会将得到的数据放在下一帧中作为剔除数据来使用,这样遮挡剔除其实是延迟一帧生效的,一般这种延迟影响不大。
UE4中默认也是采用这种方式做剔除Visibility and Occlusion Culling/index.html。
5.GPU-Driven的剔除
既然将GPU中的测试结果回传到CPU中需要很长的时间,那么为什么不直接将测试的结果保存在GPU中,然后直接根据剔除结果来选择是否绘制物体呢?
GPU-Dirven就是通过这样的思路来实现Indirect Draw。严格来说,GPU-Driven不是一种剔除算法,而是一种设计思路,其中的剔除部分仍然需要使用其他的算法来实现。
大致的流程为:
1.创建Indirect指令队列,将所有待渲染物体的渲染指令录入;
2.对渲染物体进行遮挡剔除,将剔除结果写入到buffer中;
3.根据buffer中的剔除结果,GPU会选择性执行录入的Indirect渲染指令,达到剔除的效果。
6.基于HZB剔除
HZB即Hierarchical z-buffer,HZB是多Mip层级的z-buffer,每个更高级别Mip的buffer记录上一级别中周围四点中最远处的深度值。
将HZB生成后,就可以将待剔除物体的包围盒信息传入到Computer Shader中进行计算,计算时会选择最适合的Mip级别进行遮挡测试。在屏幕中占比更大的物体会选择更高级别Mip的深度进行测试,这样可以降低计算量。
计算结果会存储到贴图或者buffer中,然后从GPU回传到CPU。这种方式和上面提到的方式一样,会有计算结果的延迟。
UE4中可通过r.HZBOcclusion=1切换到这种剔除方式。
转载声明:本文来源于网络,不作任何商业用途。

全部评论


暂无留言,赶紧抢占沙发
热门资讯

成长贴 | 之前觉得很困难的漫画创作,我6个月就学会了...

这10个免费3D模型网站你值得收藏!

3D建模私活接单APP和网站有哪些?

动漫人物手部动作素材参考!

常见的动漫人物鞋子画法教程!快来收藏吧~...

ZBrush视图切换教程!

3dmax如何解决输入文本不显示汉字的问题?...

外包约稿行为规范

【影视教程】五分钟教你看懂 LED 常亮灯参数...
