游戏中的剔除技术(一)遮挡剔除/Occlusion Culling

2022-2-27 17:21风云堂Simon51 332 0

在游戏开发中,剔除是非常重要的技术。剔除可以帮助我们将不需要的渲染开销降到最低,大幅提升游戏的帧率。

游戏中的剔除可以分成多个部分,比如 遮挡剔除、LOD、视锥剔除、硬件剔除、GPUDrivenPipeline 等。在这些里面,遮挡剔除是最难以实现的,也是变化最丰富的,这里就来小结下游戏中常用来实现遮挡剔除的方式:

1. 预计算可见性/Precomputed Visibility

这种方式比较简单,就是先将场景划分成一个个Cell,让后对于每个Cell区域,预计算出摄影机在这个Cell范围内时,所有可能看到的物体,并将信息保存下来。这样在运行时就可以直接查表来得到所有静态物体的可见信息,运行时开销几乎为0。

UE4中内置了这一功能[1],同时推荐在手机上开启此功能。

不过这种方式的缺点也很明显,完全无法剔除动态物体,静态物体可见性全部都是不可变的。

如果我们想要实现对动态物体的剔除,可以对该算法进行改进:在每个Cell中,同时保存其他Cell的可见性。对于小型的动态物体,我们先计算出动态物体所在的Cell坐标,然后根据Cell之间的可见性信息,判断可见性。这样做会额外消耗内存,如果动态的小型物体较多时,可以考虑配合使用。

Precomputed Visibility 已知应用:UE4 Mobile、逆水寒[2]

2. Portal-Culling

这种方式也是将场景划分成Cell,不同的是,烘焙时保存的是每两个相邻Cell之间的连通性。

这样,在运行时,根据摄影机所在的位置的Cell和观察方向,就可以根据Cell间的连通性信息,快速计算出目标物体是否处于可见范围内。

相对上面完全的预计算,这种方式的优点就是可以剔除动态物体,同时提供了些许的静态遮挡物体变化的灵活性。比如有扇可以开关的门,当门被打开后,就可以将门两侧的Cell的连通打开。

使用这种方式最出名的中间件方案就是Umbra[3]。Unity自带的遮挡剔除[4]就是使用的Umbra。

Portal-Culling已知应用:Unity,Control。

3. 基于软光栅/Software Occlusion

这种方式需要手动标记好大型的用来遮挡的物体,在运行时,将遮挡物的包围盒(或最高LOD级别的模型)软光栅到CPU内存中的z-buffer上,然后根据z-buffer中的深度信息,根据需要剔除物体的包围盒,实时计算遮挡信息。

这种方式缺点是对CPU端压力很大,优点是非常灵活。

相对前面两种方案,软光栅剔除提供了非常大的灵活性,支持完全可变/任意大小的场景,适用于流式关卡/大世界中的应用。

相对GPU实现的遮挡剔除,这种方案完全不用担心硬件兼容问题。

UE4的手机方案中也提供了这种剔除方式[5],设置r.mobile.AllowSoftwareOcclusion 1即可打开。

由于CPU的软光栅计算压力非常大,因此我们需要注意,不能在光栅化时计算太多的物体,不能使用精细的模型计算。由于浮点数计算很多,因此通常需要配合 SIMD[6] 技术来使用,比如 PC上的 SSE/AVX 和 ARM 下的 Neon。

Software Occlusion已知应用:UE4 Mobile,BattleField3 [7],天涯明月刀端游[8]


接下来来看基于GPU实现的剔除方案:

4. 遮挡查询/Occlusion Query

Occlusion Query首先使用一个简单的depth-only的pass将深度写入到z-buffer中,然后使用物体的包围盒传入到GPU进行遮挡测试,如果测试发现所有像素都被遮挡,说明这个物体是被遮挡的物体,否则的话认为是可见的。

包括OpenGL[9]和Directx[10]在内的图形API都提供了这种遮挡剔除。

由于从GPU回读数据到CPU通常很慢,因此通常会将得到的数据放在下一帧中作为剔除数据来使用,这样遮挡剔除其实是延迟一帧生效的。不过一般来说,延迟一帧的剔除对实际的渲染影响并不大。

UE4中默认也是采用这种方式做剔除[11]

Occlusion Query已知应用:UE4。

5. 基于HZB剔除

HZB即Hierarchical z-buffer,HZB是多Mip层级的z-buffer,每个更高级别Mip的buffer记录上一级别中周围四点中最远处的深度值。

将HZB生成后,就可以将待剔除物体的包围盒信息传入到Computer Shader中进行计算,计算时会选择最适合的Mip级别进行遮挡测试。在屏幕中占比更大的物体会选择更高级别Mip的深度进行测试,这样可以降低计算量。

计算结果会存储到贴图或者buffer中,然后从GPU回传到CPU。这种方式和上面提到的方式一样,会有计算结果的延迟。

UE4中可通过r.HZBOcclusion=1切换到这种剔除方式。

HZB剔除已知应用:UE4、原神。

参考

  1. ^https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/VisibilityCulling/PrecomputedVisibilityVolume/
  2. ^https://zhuanlan.zhihu.com/p/150448978
  3. ^https://www.gamasutra.com/view/feature/164660/sponsored_feature_next_generation_.php
  4. ^https://docs.unity3d.com/Manual/OcclusionCulling.html
  5. ^https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/VisibilityCulling/SoftwareOcclusionQueries/
  6. ^https://zhuanlan.zhihu.com/p/55327037
  7. ^Culling the Battlefield: Data Oriented Design in Practice https://www.gamedevs.org/uploads/culling-the-battlefield-battlefield3.pdf
  8. ^http://twvideo01.ubm-us.net/o1/vault/gdcchina14/presentations/833779_MiloYip_ADataOrientedCN.pdf
  9. ^https://www.khronos.org/opengl/wiki/Query_Object
  10. ^https://docs.microsoft.com/en-us/windows/win32/direct3d12/predication-queries
  11. ^https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/VisibilityCulling/

鲜花

握手

雷人

路过

鸡蛋

最新评论

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-4-20 22:27 , Processed in 0.066590 second(s), 18 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.