本文知乎地址:https://zhuanlan.zhihu.com/p/69287128
项目地址:https://github.com/MrySwk/GravityEngine
本萌新最近学习了一波关于剔除的算法,决定亲自动手写一遍,关于剔除,可以参看洛城大佬最近写的这篇文章
https://zhuanlan.zhihu.com/p/66407205
第一次学习的时候,我自然想的就是挑个最现代的终极解决方案来写,然而经过一番调查后我发现,gpu-driven可能是最现代化的一种方案,按大佬说的话来说就是现在3A大多数都是gpu-driven,然而这种做法需要改写管线里的大部分内容,对萌新非常不友好QAQ,由于我现在过于菜,太多东西没写过,所以想先把传统的cpu管线写完一遍再考虑gpu-driven。
于是我找了一遍cpu端的算法,发现英特尔在2016年提出了一种叫做Masked Software Occlusion Culling的技术,并且在网上提供了demo,我下下来跑了一下,效率高得恐怖。不过他的实现里面带了许多偏向于英特尔的优化,而且要求分occluder和occludee,只能使用大的box状的遮挡物。于是我照着他的思路重写了一遍,只用了128位的矢量化,然后深度缓冲由回读得到,而不是cpu光栅化得到,最后得到的结果比原来针对英特尔优化的版本慢了很多,但还算是落在了实际可以接受的开销范围内。
那么所谓的Mask究竟是指什么呢,在intel的这篇文章里masked指的是与hiz相对应的一种加速比较的方式,下面这张图可以大概地给个概念:
蓝线是hiz,黑线是mask,可以看出mask的效率很高,当然了,这是英特尔自己的文章里给的结论,选取的场景也是特别有利的场景。
所以我重写了一遍之后测试了一下,用的是这样的一个场景:
结果是1.45ms,如下(上面是总时间,下面是分开的时间):
因为只是光栅化bounding box,所以场景就是选择了1000个box,可以看到这里我的开销里有0.84ms是花在了reproject上了,而花在光栅化上的时间为0.5ms。
这个速度比intel的要慢一些(主要原因是我菜),其中很大的开销是花在了reproject前几帧的深度缓冲上了,也就是说这个做法是改过的,英特尔的原做法是用光栅化occluder生成的深度缓冲来做检测,这样的话是要快非常多的,因为光栅化几个大box在英特