裁剪技术

2.9k words

简介

记录常用的剔除技术

链接

AssetStore
一篇文章彻底弄懂齐次裁剪 - Clawko的文章 - 知乎 齐次空间下的裁剪
CSDN
Github 浅墨 游戏开发中的渲染加速算法总结

背面裁剪

背面裁剪是一种渲染性能优化的技术,它是将背向视点的物体或多边形删除,避免进行不必要的光栅化和深度测试。
背面裁剪可以根据多边形的法向量或顶点的索引顺序来判断是否背向视点。
背面裁剪是一种非常简单直观的操作,只能一次一对个单一多边形进行操作。

一般在光栅化阶段进行,在顶点着色器输出的顶点转换为片元的过程中,根据三角形的顶点顺序和法向量来判断哪些片元是背面,然后丢弃他们,减少片元着色器的工作量

根据三角形的三个顶点计算法向量,摄像机和三角形任意顶点的向量,点乘结果正负判断正面背面

视锥裁剪

利用空间数据结构,可以分层地来应用这种裁剪。例如,对于层次包围体BVH来说,从根节点进行先序遍历(Preorder Transversal),就可以完成这一任务
Iamge text

除了层次包围体,其他的空间数据结构同样也可以用于视锥裁剪,包括上文提到的八叉树和BSP树。但是当渲染动态场景时,这些方法便会显得不够灵活,不如层次包围体

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

遮挡剔除

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

遮挡地平线算法是基于点的可见性来判断的。有些时候采用基于单元的可见性方法更合适,但基于单元通常比基于点的可见性计算复杂度要高得多。Wonka等人提出了一种称为遮挡物收缩(Occluder Shrinking)的方法,可以使用基于点的遮挡算法来生成基于单元的可见性,根据给定的量来缩小场景中所有遮挡物来达到延伸有效可见点的目的。他们也提出了一种视锥扩张(Frustum Growing)技术,通常与Occluder Shrinking算法一起配合使用

Image text

  1. Hardware Occlusion Queries 硬件遮挡查询
    当和Z缓冲器中内容进行比较时,用户可以通过查询硬件来找到一组多边形是否可见的,且这些多边形通常是复杂物体的包围体(如长方体或者k-DOP)。如果其中没有多边形可见,那么便可将这个物体裁剪掉。硬件实现对查询的多边形进行光栅化,并且将其深度和Z缓冲器进行比较

  2. Hierarchical Z-Buffering 层次Z缓冲

    • 尽管其在CPU上很少使用,但该算法是GPU上做Z-Culling(深度裁剪)的基础
    • 层次Z-缓冲算法用八叉树来维护场景模型,并将画面的Z缓冲器作为图像金字塔(也称为Z-金字塔(Z-pyramid)),该算法因此在图像空间中进行操作。其中,八叉树能够对场景的遮挡区域进行层次剔除,而Z-金字塔则可以对单个基元和边界体积进行层次Z缓冲。 因此Z-金字塔可以作为此算法的遮挡表示
    • Image text
    • 在这个例子中,遮挡八叉树节点的裁剪可以将深度复杂度从84,降低到了2.5
  3. Occlusion Horizons 遮挡地平线

    • 基本思想是裁剪掉位于地平线之间和之下的物体。 这种类型的算法经常被用来高效绘制如城市和村庄一样的城市环境。
    • 通过从前到后渲染一个场景,我们可以定位到地平线在哪里进行渲染,而任何在当前地平线之后和之下的物体都可以被裁剪掉
  4. Occluder Shrinking 遮挡物收缩

  5. Frustum Growing视锥扩张

  6. Virtual occluder 虚拟遮挡物算法

  7. Shaft Occlusion Culling 轴遮挡裁剪

  8. The HOM algorithm 层次遮挡映射算法

    • 类似层次Z缓冲算法,是一种启用分层图像空间剔除的方法。但其也不同于层次Z缓冲,因为它提供了使用近似遮挡剔除的能力。 HOM算法的基本思想是,每帧建立一个分层深度缓冲区,用于遮挡测试。并且在每个级别使用不透明度阈值来确定是否有足够的要渲染的对象是可见的。如果只有一小部分的对象是可见的,那么该对象被剔除。但作为一个基于CPU的算法系统,这个算法已经不受欢迎了
  9. Ray Space Occlusion Culling 射线空间遮挡剔除

像素裁剪

像素剔除又称为距离剔除,其原理就是当我们缩放视图时,对于离我们相机很远的物体,则不绘制。当物体很远时,我们肉眼已经很难分辨出来,再绘制它其实也是白白浪费GPU计算资源

像素剔除的计算有两种策略:第一,每次Render时, 先计算一遍所有物体包围盒在屏幕上的投影大小,算出其投影占据的面积,用像素表示,用户可以给定一个可以显示的最小像素阈值。
小于该阈值的则不需要进行绘制。第二种,每次Render前计算出物体与相机位置之间的距离L,同时与计算出物体的包围球的直径R,计算出其直径R与距离L的比值ratio = R/L。同时给定一个阈值,当比值小于该阈值时则不进行绘制。
相比于第一种计算投影面积的像素,第二种方法更高效,像素剔除对于场景中有
很多小物体会很有用,比如智慧城市中的树木,机械装配体中的小零件,BIM中的管道接头等。Hoops引擎中自带像素剔除的功能

层次视锥裁剪

入口裁剪

对建筑物模型来说,很多裁剪方面的算法可以归结为入口裁剪(Protal Culling)。在这个方向,最早的算法由Airey提出,随后Teller和Sequin,以及Teller和Hanrahan构造出了更高效,更复杂的算法。入口裁剪算法的基本思想是,在室内场景中,建筑物墙面通常充当大的遮挡物,通过每个入口(如门或者窗户)进行视锥裁剪。
当遍历入口的时候,就减小视锥。使得与入口尽可能紧密贴合。因此,可以将入口裁减算法看作是视锥裁剪算法的一种扩展,且需将位于视锥之外的入口丢弃。需要考虑反射(反射区域内的物体不被裁剪)
Image text

细节裁剪

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