几种剔除:
背面裁剪(Backface Culling
视锥裁剪(View Frustum Culling)
遮挡剔除(Occlusion Culling)
层次视锥裁剪(Hierarchical View Frustum Culling)
入口裁剪(Portal Culling)
细节裁剪(Detail Culling)
像素剔除(Pixel Culling)

在计算机图形学中,相对应的就是裁剪技术(Culling Techniques)所要做的工作——“从大量游戏事物中进行删除”。所谓的“大量事物”就是需要绘制的整个场景,删除的是对最终图像没有贡献的场景部分,然后将剩余场景发送到渲染管线。因此,在渲染方面通常使用“可见性裁剪(Visibility Culling)”这个术语。但其实,裁剪也可以用于程序的其他部分,如碰撞检测(对不可见物体进行不十分精确的计算)、物理学计算,以及人工智能(AI)领域。
背面裁剪即是将背向视点的物体删除,是一种非常简单直观的操作,只能一次一对个单一多边形进行操作。
视锥裁剪是将视锥之外的多边形删除,相对而言,这种操作比背面裁剪稍微复杂。
遮挡裁剪,是将被其他物体遮挡的物体进行删除,这种操作在三者中最为复杂,因为其需要聚集一个或者多个物体,同时还需使用其他物体的位置信息。
渲染性能优化之Culling 剔除-编程知识网
其中被裁剪掉的几何体用虚线表示

背面裁剪 | Backface Culling

渲染性能优化之Culling 剔除-编程知识网

确定多边形是否背向的两种不同测试。左图所示为屏幕空间的测试情形,三角形和四边形是正向,而七边形是背向。对背向的七边形,无需进行光栅化。右图为视点空间中背面测试情形,多边形A是背向的,而B和C是正向的。多背向的多边形A,无需进行光栅化。

视锥剔除(Frustum Culling)

视锥是指的相机的视锥体(Frustum),如果是透视投影则是平截头状,如果是正交投影则是一个立方体形状。
渲染性能优化之Culling 剔除-编程知识网
渲染性能优化之Culling 剔除-编程知识网

如上图中绿色的球在位于视锥外面,则会被视锥剔除掉。如果不进行剔除的话,则绿色的球会被传到GPU端进行渲染。但实际其并不会被显示,对它的计算是浪费的。如何判断一个对象在不在视锥体外面,最简单的方法是判断该对象的包围盒是不是在视锥的外面,视锥是由六个面组成,可以判断对象包围盒与六个面之间的关系来进行剔除计算。视锥剔除可以大大的提高图形的显示效率。成熟的图形引擎应该都有视锥剔除,如Hoops,VTK等,对于一个大场景我们放大视图,视图越大,可以发现缩放等操作会更加流畅。

像素剔除(Pixel Culling)

像素剔除又称为距离剔除,其原理就是当我们缩放视图时,对于离我们相机很远的物体,则不绘制。当物体很远时,我们肉眼已经很难分辨出来,再绘制它其实也是白白浪费GPU计算资源。
渲染性能优化之Culling 剔除-编程知识网
像素剔除的计算有两种策略:第一,每次Render时, 先计算一遍所有物体包围盒在屏幕上的投影大小,算出其投影占据的面积,用像素表示,用户可以给定一个可以显示的最小像素阈值。小于该阈值的则不需要进行绘制。第二种,每次Render前计算出物体与相机位置之间的距离L,同时与计算出物体的包围球的直径R,计算出其直径R与距离L的比值ratio = R/L。同时给定一个阈值,当比值小于该阈值时则不进行绘制。相比于第一种计算投影面积的像素,第二种方法更高效,像素剔除对于场景中有很多小物体会很有用,比如智慧城市中的树木,机械装配体中的小零件,BIM中的管道接头等。Hoops引擎中自带像素剔除的功能。

入口裁剪 | Portal Culling

对建筑物模型来说,很多裁剪方面的算法可以归结为入口裁剪(Protal Culling)。在这个方向,最早的算法由Airey提出,随后Teller和Sequin,以及Teller和Hanrahan构造出了更高效,更复杂的算法。入口裁剪算法的基本思想是,在室内场景中,建筑物墙面通常充当大的遮挡物,通过每个入口(如门或者窗户)进行视锥裁剪。当遍历入口的时候,就减小视锥。使得与入口尽可能紧密贴合。因此,可以将入口裁减算法看作是视锥裁剪算法的一种扩展,且需将位于视锥之外的入口丢弃。
渲染性能优化之Culling 剔除-编程知识网
单元分别从A到H,入口是连接单元的通路,只对穿过入口能看到的几何体进行渲染。

渲染性能优化之Culling 剔除-编程知识网
左图为房间顶视图,白线表示每一个入口的截锥体减少的方式。红线是在镜子上反射圆台来产生的。实际视图显示在右侧的图像中。

细节裁剪 | Detail Culling

细节裁剪(Detail Culling)是一种通过牺牲质量换取速度的技术。其基本原理是,当视点处于运动的时候,场景中的微小细节对渲染出的图像贡献甚微。,当视点停下来的时候,通常禁止细节裁剪。
考虑一个具有包围体的问题,将这个包围体投射到投影平面,然后以像素为单位来估算投影面积,如果像素的数量小于用户定义的阈值,那么不对这个物体进行进一步处理。基于这个原因,细节裁剪也往往被称为屏幕尺寸裁剪(Screen-Size Culling)。细节裁剪也可以在场景图上以层次形式来实现,几何阶段和光栅阶段都可以从这个算法中受益。
另外,细节裁剪还可以作为一种简化的LOD技术来实现,其中一个LOD是整个模型,另外一个LOD是空物体。

遮挡剔除 | Occlusion Culling

遮挡裁剪(Occlusion Culling),也常被称作遮挡剔除。
聊一聊遮挡剔除必要性。不难理解,可见性问题可以通过Z缓冲器的硬件构造来实现,即使可以使用Z缓冲器正确解决可见性问题,但其中Z缓冲并不是在所有方面都不是一个很“聪明”的机制。例如,假设视点正沿着一条直线观察,其中,在这条直线上有10个球体,虽然这10个球体进行了扫描转换,同时与Z缓冲器进行了比较并写入了颜色缓冲器和Z缓冲器,但是这个从这个视点渲染出的图像只会显示一个球体,即使所有10个球体都将被光栅化并与Z缓冲区进行比较,然后可能写入到颜色缓冲区与Z缓冲区。中间部分显示了在给定视点处场景的深度复杂度,深度复杂度指的是对每个像素重写的次数。对于有10个球体的情形,最中间的位置,深度复杂度为10,因为在这个地方渲染了10个球体(假设背面裁剪是关闭的),而且这意味着其中有9次像素写入是完全没有必要的
渲染性能优化之Culling 剔除-编程知识网

在现实生活中却很常见,如热带雨林,发动机,城市,以及摩天大楼的内部。下图显示了曼哈顿式城市的示例。左图为视锥裁剪后的图示,中图为视锥裁剪后的图示,右图所示为遮挡剔除和视锥裁剪后的图示
渲染性能优化之Culling 剔除-编程知识网

从面给出的示例可以看出,这种用来避免低效率的算法可以带来速度上的补偿,具体可以将这些方法归类为遮挡裁剪算法(Occlusion Culling Algorithms),因为它们都试图裁剪掉被遮挡的部分,也就是被场景中其他物体遮挡的物体,最优的遮挡裁剪算法只选择其中可见得的部分。有两种主要形式的遮挡裁剪算法,分别是基于点的遮挡裁剪和基于单元的遮挡裁剪。

总结

在考虑渲染优化的问题上,应当优先考察”视椎体剔除”和”遮挡剔除”是否在项目中正常运作,这两项会极大的影响到实际渲染时的消耗。其次需要考虑背面剔除的开启,在没有大量使用单面的模型情况下,背面剔除可以在不影响显示的前提下少处理一半的像素着色运算。视口剔除和深度剔除是渲染管线的固有部分,不在优化的主要考察范围内。当然剔除往往与LOD结合在一起。

渲染性能优化之LOD的几种LOD层次细节总结