Hi-Z GPU Occlusion Culling

Hi-Z GPU Occlusion Culling

在之前的GPU Driven RP中我们已经实现了视锥体剔除,并没有实现遮挡剔除,这篇文章也拖了许久,后来在群里Steven大佬的耐心讲解下对Temporal Reprojection Culling有了一点了解,并且实现了一下。

唔。。反正看这篇文章的大多数是已经跟着之前文章过来的老朋友了,该会的大家都会,闲话不多说,直接撸核心思路。标题图用的是 Assassin's Creed Unity的宣传画,实际上这项技术最早几乎就是在大革命中被使用到的,通过使用上一帧的摄像机位置(包括矩阵)和上一帧的深度图做剔除,储存已经被剔除的物体和未被剔除的物体,然后绘制未被剔除的物体到GBuffer(包含深度图),再二次生成HiZ DepthTexture,并对已经被剔除的物体使用一遍新的深度和当前摄像机的位置做一次剔除判断。不过在实战测试中。。如果场景复杂度不是特别高,帧数比较稳定,不容易出现上一帧被遮挡的物体这一帧突然出现的情况,其实也可以放弃掉后半部分的二次剔除,为节省性能选择对剔除结果错误的一些容忍。

不多说直接上代码,第一个Dispatch负责将未被遮挡的物体和被遮挡的物体分别存入两个StructuredBuffer里,这就意味着要同时开两个Buffer,显存占用会增加,不过在Buffer中只储存integer,因此显存占用也并非难以接受:

PlaneTest之前已经提到过,将传入的6个平面与每个Cluster做对比。这里着重要描述一下遮挡剔除的算法,遮挡剔除的算法是,首先判断bounding box的大小,这里的“大小”是指其在投影范围内的大小,也就是近大远小,这个判断可以根据其最远点到中心的投影长度的xy,也就是屏幕UV来决定。有了这个距离,就可以判断出即将使用的深度LOD层级,最后分别比较上下左右前后6个点判断bounding是否完全被深度图遮挡(还有一种办法是使用view space的山下左右判断,但是经过本人测试这种方法的剔除力度不够强大,许多时候物体显然被遮住了却可能没被剔除)。

其具体代码实现如下:

那么第一部分的执行就已经结束了,“被剔除”的物体队列和“没有被剔除”的物体队列都已经被储存了下来。因此我们可以直接开始绘制确定“没有被剔除”的物体,这些物体即将重置上一帧的深度,并获得当前帧的正确的深度,重新生成深度图的LOD。拥有了新深度图之后再次对“已经被剔除”的物体执行Indirect Dispatch,这一步的存在单纯是为了防止上一帧被剔除但是这一帧不应该被剔除的物体被错误的剔除掉(比如上一帧主角还在墙后,这一帧突然走出来,视野一下变开阔),遮挡剔除应该保守,因此我们“宁滥勿缺”,保证所有可能被看见的物体都被绘制:

这一段代码有点“大纲”的意思,因为本人的编程习惯,喜欢把函数和逻辑分开,以便防止传统面向对象的耦合度在开发后期代码量时搞昏了大脑,这些实现都会上传到开源,这里就不详细展开了,实际函数实现比较简单,基本就是传入刚才在Compute Shader中用到的Buffer和Texture然后Dispatch。

值得一提的是最后一步Occlusion Recheck,这一步执行了二次扫描所有被上一帧深度剔除的物体,并决定哪些本来是不应该被剔除的:

dispatchBuffer[3]储存着总dispatch数量,而dispatchBuffer作为当前compute shader的indirect buffer,dispatchBuffer[0]储存的是线程组数量,也就是ceil(dispatchBuffer[3] / 64.0),这并不难以理解。reCheckResult开的另一个储存剔除结果的Buffer,虽然这会导致显存的占用更高,但是这些储存结果的Buffer均储存索引值,只有4位的int占用空间是远小于Cluster本身信息的,因此可以认为这样的占用对显存来说并不是特别不友好。

最后一步则是使用了_VP矩阵,也就是当前帧的矩阵,配合已经传入的新的HizDepthTexture进行基于深度的剔除。

说了这么多,绘制的结果如何呢。

我们在自定义的Debug模式中逐帧分析:

先用场景内的椅子背挡住视线
下一帧已经被剔除的七零八落的场景(因为上一帧摄像机的视线深度完全被覆盖)
经过二次补充以后,场景恢复正常绘制

可见,这样的效果正符合我们设想的预期,已经上传的源码地址如下:

MaxwellGengYF/Unity-GPU-Driven-Pipelinegithub.com图标

注意,截止到发稿前,源码使用的是2018.3b7版本,之所以要用新版本主要是为了使用C#7.3带来的新特性,否则有些数据结构将会报错!另外,由于本人真的很懒,所以到现在也没开始写框架说明和文档,之后一定会写的……

在之后的文章中,我们将着手于画面的处理,提供点光源,聚光源以及反射球和一些后处理的设计。而材质和大地形曲面细分还需要往后再排排。。

发布于 2018-10-28

文章被以下专栏收录