作者:Siney

现在的HSR算法基本上可以分为四种:backface culling、frustum culling、portal culling、occlusion culling。它们的作用分别如下:backface culling用于剔除mesh背面的triangle,frustum culling用于剔除屏幕之外的物体,portal culling用于剔除不能通过portal看到的物体,而occlusion culling用于剔除场景中被自己前面的物体所遮挡的物体。其中前两种算是最常用的算法了,对于backface culling来说它已经在GPU的硬件上实现,不过为了减少传输带宽,在适当的地方你也可以将其使用到CPU部分,主要是指地形这样的大规模MESH上,如何使用这需要看你是如何组织地形数据的,当你使用triangle strip渲染地形时,尽量按块来对地形进行culling,而当你使用triangle list来渲染地形时,你就可以尝试使用逐triangle来对其进行culling,关于实际使用应该使用哪种方法,需要你自己试验一下。frustum culling由于太普遍这里不再解释,而portal culling如果详细介绍的话那就是另外一篇文章了,简单的说就是如果相机不能通过一扇门看到房子,那么房子里的所有物体都被culling掉而不需要渲染,下面我举一个简单的例子来看看它为什么不能作到完全的剔除:

上面可以看作是一个房子,Portal为房间的门,如果我们做portal culling计算时,npc是可见的,但由于前面存在物体wall,应当是不可见的,但是portal culling并没有将其剔除,因此npc还是会被传送到GPU进行渲染。

  这个时候就需要可以使用occlusion culling技术来弥补这个缺憾了,因此在一个portal引擎中必然需要OC技术来配合使用,这里再举一个outdoor的例子,在室外存在一个building,我们可以使用building的门和窗户作为portal来对building内部进行culling,将building作为一个occluder对整个场景进行OC操作。根据相关文献提供的资料,当场景使用OC技术后会比不使用OC的场景提高30%到70%不等的FPS,因此如果有可能的话应尽量将OC技术加入到你的引擎中,而且OC技术并不是只能使用到portal引擎中,它可以被使用到任意技术构建的引擎中。

  现在的OC算法非常多,比较优秀的如HZB、HOM算法虽然比较强悍,但是放在CPU进行计算的话,效率还是非常低的,达不到实时的要求,而当前的GPU还没有对其实现硬件的支持,因此不是本文介绍的重点,这里介绍的OC算法称为区间扫描线Z缓冲器算法,这是一种可以进行完全剔除并且效率非常高的一种OC算法。在进行介绍前我们必须明确几个概念,在OC中遮挡物被称为occluder,被遮挡物称为occludee,OC算法就是检查occludee是否被occluder所遮挡。

场景中那些比较大的物体可以作为occluder,如房屋,城堡等,进行OC计算之前我们首先需要获得场景中的所有occluder,这是非常重要的一个步骤,这一步通常在场景的预处理时进行,根据场景来产生一个occluder列表并保存到文件中。

  下面我们讨论一下如何获得occluder,场景中的occluder通常需要手工进行指定,这是因为开发一个自动获得occluder的算法非常复杂,同时由于OC运算效率问题同一帧中出现的occluder数量必须进行限制。现在MMO比较流行的基于terrain的引擎,场景中可以作为occluder的物体其实都是一个个单独的model,因此求occluder实际上就变成获得model的convex hull,这类算法也比较多如qhull算法,但是如果使用程序获得hull的话对model的外形存在一定的限制,一个替代的方法是在美工对物体进行建模时同时为其指定一个hull并保存到文件中,这样的话就不会限制model的形状了,因此对于第二种情况概括起来说就是在编辑场景时指定适当的物体作为occluder,然后将物体的convex hull保存到occluder list中。

  当我们获得场景中的occluder就可以进行OC运算了,先来看看区间扫描线Z缓冲器算法是依照什么样的原理来实现OC的。

occluder上位于同一平面上的多边形称为surface,surface上由edge首尾相连构成一个闭合的空间。

在上图中物体N为occluder,A、B、C为occludee,我们假定它们投影到屏幕上都为一个矩形,我们这里称N的上下两条edge a、b为扫描线,从上图中可以看出如果物体A位于N的后面那么A一定被N所遮挡,这可以通过比较N和A所在surface的z值来进行比较,这也就是本算法中Z缓冲器的来历,现在我们假设物体A、B、C都位于N的后面,可以看出A被完全遮挡,B是部分遮挡,C没有被遮挡,如何判断呢?

先看A的情况,N和A存在四条扫描线按照y从小到大顺序分别是b,d,c,a,在扫描线b和d构成的区间中由于不存在A的edge因此跳过,检查扫描线d和c构成的区间,我们称位于两条扫描线之间的edge为活化边,它们保存在活化边列表active edge list中,每一条活化边保存了两个surface指针,分别是左surface和右surface,例如对于N的左edge而言,它的左surface不存在因此指向屏幕的background,也就是z值为最大的surface,而右surface为N所在的surface,其他类似。

现在我们检查扫描线d和c之间的活化边列表,首先获得A的x值最小的活化边为A的左edge,接着获得N的活化边列表中x大于A的左edge的活化边,为N的右edge,比较两条edge的左surface,A的左edge的左surface的z大于N的右edge的左surface的z,因此A的左edge被N所遮挡,接着同样的方法检查A的右edge还是被遮挡,这样我们就可以判断A完全被N所遮挡。使用同样的方法检查B,在扫描线f和b构成的区间中,由于N不存在活化边列表可以判断B没有被N完全遮挡。再检查C,在扫描线h和g之间N的活化边列表中所有的edge的x都小于C的左edge,可以判断C没有被N遮挡。对于其它复杂的情况例如存在多个occluder的情况你自己可以验证,这种算法在任何情况下都可以对物体是否被完全遮挡进行精确的判断。

通过上面的介绍相信你已经完全理解区间扫描线Z缓冲器算法的基本原理,下面看一下具体如何来实现这个算法,步骤如下:

1 、获得场景中所有的occluder,剔除occluder上所有背对camera的surface。

2 、使用near clip plane对所有的surface进行clip操作,剔除位于near clip plane之外的surface,如果surface和near clip plane相交计算交点,这样也就剔除了那些位于nearclip plane之外的edge。

3 、将所有的顶点变换到投影空间,这里需要注意投影空间的性质,投影变换实际上就是将frustum变换为一个BOX,对于openGL来说就是一个立方体,最小拐点为(-1,-1,-1),最大拐点为(1,1,1),对于DX来说是一个长方体,最小拐点为(-1,-1,0),最大拐点为(1,1,1)。在投影空间所有物体投影到屏幕上形状不会发生改变,这也是为什么要变换到投影空间的原因。计算每一个surface在屏幕上的投影面积,剔除那些面积过小的surface,剔除位于frustum之外的surface,但是并不对surface求交,这是为了防止因为计算精度的原因出现错误。将surface所在的plane也变换到投影空间,这样做是为了方便计算指定顶点的z值。

4 、将变换到投影空间中的所有顶点保存到edge list中,注意edge保存方式,edge起点的y值应当小于终点的y值,并且我们称起点处的y值为edge的y值。在edge list中按照edge的y对所有的edge按照从小到大的顺序进行排序,如果y相同比较x值,如果x也相同比较edge的斜率。因为edge list完全按照y进行排序,因此我们也可以称其为Y桶。需要注意的是如果edge和X轴平行的话,并不需要将其加入到edge list中。

5 、查找扫描线并计算扫描线之间的活化边列表。从上面的原理介绍中我们也能大致了解如何获得扫描线,扫描线必然位于edge的端点上,而且如果edge存在相交的话,那么交点也需要做为扫描线,那么我们需要对Y桶进行遍历来查找位于扫描线Y=-1和Y=1之间所有的扫描线,当获得所有的扫描线后接着需要计算扫描线区间的活化边列表,注意活化边列表中的edge需要使用edge与扫描线之间的交点作为端点,并且活化边列表是按照x进行排序,因此也可以称为X桶。

6 、对场景需要检查是否被遮挡的物体传入它的AABB作为occludee,首先检查occludee在屏幕上的投影面积是否足够大,如果太小不需要对其进行OC,接着将AABB转换为一个BOX,计算BOX的surface和edge,将其变换到投影空间并按照上面的方法查找扫描线并获得活化边列表。从occluder和occludee中y最小的扫描线出发,逐区间对活化边列表进行比较检查occludee是否被完全遮挡。

  在这种算法中,几乎每帧都需要对活化边列表进行更新,因此计算量最大的部分也在这里,不过一旦活化边列表建立以后对occludee进行遮挡计算非常方便快捷,适合对大量的动态物体进行OC运算,尤其是那些渲染代价非常大的角色模型。

[HSR算法-Occlusion Culling]相关推荐

  1. GPU Driven Occlusion Culling(Hiz)

    最近集成遮挡剔除算法,最终从各种算法预研收敛到HIZ算法(此算法也可快速将视锥剔除集成进来做到剔除算法全部采用GPU驱动为主,可参照Vulkan_基于GPU的视锥体剔除和LOD),因此本部分我们来着重 ...

  2. Unity - 搬砖日志 - Occlusion Culling 关闭动态遮挡剔除 Renderer.allowOcclusionWhenDynamic = false

    文章目录 CullDynamicObjectsWithUmbra 消耗 如何禁止 动态对象的遮挡剔除的消耗 写工具来遍历 Renderer.allowOcclusionWhenDynamic = fa ...

  3. Occlusion Culling 遮挡剔除 相机系列5

    Occlusion Culling 遮挡剔除 本文档主要是对Unity官方手册的个人理解与总结(其实以翻译记录为主:>) 仅作为个人学习使用,不得作为商业用途,欢迎转载,并请注明出处. 文章中涉 ...

  4. Unity_7 如何使用遮挡剔除Occlusion Culling

    什么是Occlusion Culling(遮挡剔除) 当一个物体被其他物体遮挡住而不在摄像机的可视范围内时不对其进行渲染. 在绝大多数情况下离 camera 最远的物体首先被渲染,靠近摄像机的物体后渲 ...

  5. Occlusion Culling(遮挡剔除)

    Occlusion Culling(遮挡剔除) 本文转载自:https://www.jianshu.com/p/d15eeae757a3 什么是Occlusion Culling(遮挡剔除)? 遮挡剔 ...

  6. (转) Occlusion Culling(遮挡剔除)

    转自 作者:JervieQin 链接:https://www.jianshu.com/p/d15eeae757a3 什么是Occlusion Culling(遮挡剔除)? 遮挡剔除, 当一个物体被其他 ...

  7. Unity3D-游戏场景优化之遮挡剔除(Occlusion Culling)的使用

    在大型3D游戏场景中,如何优化游戏性能是非常重要的一步.一般遮挡剔除是非常常用的.接下来我们看看如何使用遮挡剔除. 假设这是一个游戏场景. 下面这是相机的视口,相机的视觉是看不到很大立方体后面的那些小 ...

  8. Occlusion culling

    遮挡剔除(仅专业版) Occlusion Culling (Pro only) Date:2013-04-25 11:50 Occlusion Culling is a feature that di ...

  9. Unity 3D 遮挡剔除(仅专业版) Occlusion Culling (Pro only)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Occl ...

最新文章

  1. 实收资本、资本公积、盈余公积的含义和区别
  2. Sublime Text for Windows的快捷键
  3. android设置控件形状,Android控件自定义形状
  4. python的继承与多态
  5. 【matplotlib笔记】3D图像绘制
  6. mysql多次join后count优化_mysql join count 优化案例
  7. mysql死锁——mysql之四
  8. poi根据模版导出多页word,带插入图片,并压缩下载
  9. 计算机求和便捷应用,4种常用求和方法 | Excel自动求和全攻略!
  10. 英语在线教育机构争战AI风口,为何雷声大雨点小?
  11. 软件企业必备的认证资质证书
  12. 计算机安全凭据,4776 (S、F) 计算机尝试验证帐户的凭据。 (Windows 10) - Windows security | Microsoft Docs...
  13. oCPC实践录 | 广告算法工程师的自我修养
  14. manjaro安装tim
  15. 阿里大鱼短信平台使用(Java)
  16. 网狐架设,中心服务器错误数据库异常:[DBNETLIB][ConnectionOpen (Connect()).]SQL Server 不存在或拒绝访问
  17. 用PS给外景人像添加逆光效果
  18. 计算机网络原理笔记 精整理 第六章 应用层
  19. 试题 算法训练 进击的青蛙
  20. MyDockFinder

热门文章

  1. 计算机工程应用是什么期刊,计算机工程类期刊汇总
  2. 雷曼光电:LED行业黑马闪亮上市
  3. QQ(微信)一次性发送多条信息(连续发520遍我爱你)
  4. 图解卡尔曼滤波(Kalman Filter)
  5. 什么是龙格现象(Runge phenomenon)?如何避免龙格现象?
  6. 解决No EPCS layout data --- looking for section [EPCS-xxxxx]
  7. Matlab绘制多组柱状图的方法(可直接复制)
  8. 深度学习细粒度图像研究汇总
  9. Node.js与相关依赖的版本对照表
  10. 视频理解论文实验笔记2014-2022