对于realtime interactive 3d environment,现实的速度是非常重要的,虽然现在的硬件能力非常的快,但是要想保持30FPS的同时处理数十万的三角形,以现在的主流机器来说还是非常困难的。

  为了解决这种问题,人们提出了很多方法,其中有LOD,有Culling,对于LOD,它可以从2FPS提高到10FPS,但是很难从4FPS提高到20FPS。这两种方法并不矛盾,而且我们往往需要在culling的基础上再使用lod进一步解决pipeline的负担。

  这里我主要希望讨论一下culling方面的技术:culling的意思是select from a flock,就是“从一群里面选择一部分“。对于3d engine来说,就是要从几十万的triangle之中选择出一小部分送给pipeline进行渲染。

选择的方法总的来说有如下几种途径:

  最简单的就是backface culling,这个已经很普通,我就不说废话了。

  然后就是view frustum culling,只选择在view frustum中可见的部分送入pipeline,通常人们会采用hierarchy的数据结构来有效的进行view frustum culling,层次型的结构在各种图形学算法中普遍采用,比如碰撞检测,光线追踪,radiosity等等。我尝试过一种基于AABB Tree的view frustum culling,加上frame coherency,plane masking等优化的方法之后,我认为效率已经非常高了。

但是对于现在的游戏场景viewfrustum culling是远远不够用的,因为view frustum实在是非常的大,现在的场景又非常的复杂,采用view frustum culling对于场景漫游的视角来说,平均可以删除场景中60%左右的数据,对于一个100,000triangle的场景来说,剩下的数据也会有好几万多边形,对于pipeline来说依然是比较重的负担。

  不过view frustum culling是最容易实现的算法了,非常的方便和有效,对于一部分3d rpg来说,我认为是一个不错的选择,因为你可以要求camera处于较高的位置,并且总是向下观察,这样用view frustum culling就可以以非常低的代价筛选出很少的一部分场景数据了,对于《格兰蒂亚》,《星辰物语》,还有最新的《绝冬城之夜》等,是足够了,他们对于镜头都有比较严的限制,正好适用于viewfrustum culling.如果大家想做3d游戏,还是先从这类游戏入手的好,因为可以直接集中精力于渲染技术和其他有趣的部分。

  但是对大部分第一人称射击游戏而言,view frustum culling是远远不够的,事实上,在实际的环境中我们的视野总是被各种物品遮挡住,所以我们往往只能看到整个场景中的一小部分,远远小于我们的view frustum的范围。这些物品被称作occluder,所以有很多方法就是在考虑如何使用occlusion culling来提高显示的性能。然而,occlusion culling比起view frustum culling复杂度上升的太多,直径也很难找到一个很完美的解决方案,下面我就将现有的一些途径简单的介绍一下:

  这些方法都有需要将整个场景进行层次划分(用bsp tree,kd-tree),分解成一个个cell。可见性判别的力度往往就是到达cell的级别,你可以根据自己需要决定cell的粒度来平衡效率。

  先介绍run-time的一些方法:

  1.基于portal的occlusion culling,
  这是一种基于object space的run-time method,这种方法特别适用于全封闭的建筑类场景,洞穴类场景,因为这些场景有一个特点,遮挡非常明显,比如一个大楼,每个房间(cell)的大部分都被墙壁所遮挡,只能透过少数的门,窗看到场景中的其他部分。对于这种场景,我们可以采用如下的方法进行有效的culling:
  首先,识别出场景中每个cell的portal(门,窗),渲染的时候,找到view point所在的cell,然后view frustum从当前cell开始,一次通过该cell的portal来遍历场景,每经过一个portal,  就对view frustum进行一些修正,因为这些portal与视点形成更多的限制,直到看不到任何portal位置。遍历过的cell就是可见的cell.

这种方法对于这类场景非常有效,因为通常我们的遍历透过几扇门窗就停止了。portal需要事先人工设置,或者用算法自动识别。然而对于很多户外场景,很难存在这样的cell和portal,因此对于那些场景这个方法就不适用了。

  2.single occluder culling
  在portal算法的基础上,这又是一种基于object space的run-time method,这种方法可以用于那些有很多高大的遮挡物的场景,比如大都市,高山环绕的场景。这些场景的特点是,存在很多单个的高大有效的遮挡物,比如大山,大楼,他们往往能够遮挡住viewfrustum中的很多部分。当然对于portal算法对应的室内场景该方法也同样适用。算法的过程如下:

  维护一个occluder列表,利用层次性的结构,从视点出发,以从前往后的顺序访问各个cell,判断是否被occluder列表中的某个occluder挡住,如果没有对于该cell中的物体,判断它是否是比较好的occluder(根据它在是平面上的投影面积等因素),如果是则加入occluder列表,继续遍历。

这种方法有时也会采用一些与处理的过程,标记一些物体为好的occluder,或者生成一些virtual occluder(外形更加简单,近似代替一些occluder),这些都是为了减少运行时选择occluder的时间,以及让occluder的选择更加有效。

  这种方法的缺陷是,无法考虑几个occluder共同的作用效果,有很多东西也许既不能被occluder A挡住,也不能被occluder B挡住,但是有了occluder A和B,你确实看不见这个东西了。所以对于没有非常大的occluder的但是仍然遮挡很密集的场景,比如丛林,这个方法一点用也没有。然而要想在run-time的时候考虑多个occluder共同的影响(在object-space中),是非常难以做到速度的保证(计算的代价太大)。
  3.由上面两个例子,可以看出如果可以考虑多个occluder的作用影响,那么viewfrustum中的部分就可以限制得非常多,而且也可以处理更加复杂的场景。但是像在object-space中处理这种情况实在是很难以很低的计算代价来获得。因此一些基于image-space的方法就诞生了。最普通的例子就是z-buffer.利用image-space来处理的好处就是image-space的可见性是由有限的元素(屏幕上的像素个数)来决定的,比起object-space有很大的优势。但是依靠z-buffer已经到达了渲染阶段,是不够的。有一种hierarchy z-buffer的做法,也称作z-pyramid,因为它生成一系列的不同精细度的z-buffer,比如,最大的z-buffer是32*32的一块suface,那么它生成16*16,4*4,2*2,1*1的另外4级z-buffer,每一级z-buffer对应上一级中的四个像素,并且取其中的最远深度。因此我们在绘制场景的时候可以通过层次性结构,从前往后渲染,并且每次可以先拿层次结构中的结点的bounding box先进行比较(从最粗的那一级z-buffer开始),那么就可以非常有效的绘制遮挡关系复杂的场景。这种方法我感觉非常有希望,但是唯一不足的是如果没有硬件的支持,考软件的方法来实现这种z-pyramid以及相应的检测,速度还是非常慢的。
  因此我认为如果以后硬件开始很好的支持z-pyramid,那么这会是一个非常好的方法,说不定会成为一个标准方法,就像现在的z-buffer那样。

  4.image-space确实是一个解决多个occluder共同影响可见性的好途径,但是没有硬件的支持,使得他的效率降低。然而对于某些特殊的环境,可以采用一些特殊的方法,使得我们也可以将objec-space和image-space的方法结合起来从而得到一个比较好的trade off.这种场景就是那些2.5d的场景,最常见的就是城市环境。基本上,绝大部分在城市场景的游戏都可以看作是2.5d的环境,可见性的判断只要在2d的基础上考虑一下高度的因素就可以了。
  因此这里有一个方法可以有效的处理城市的环境。算法如下:首先将cell的划分严格限制在平面上(比如水平的地面上),比如256*256个cell的方格,大小和粒度可以根据具体的场景来决定。每个cell记录属于该cell的objects(需要绘制的),以及该cell中最高object的高度。为了提高效率,也需要事先标记一些良好的occluder,比如各个楼房的正面,不过这里有一个限制,就是occluder必须是垂直于水平面的矩形。
  有一个surface buffer,比如我们这里的是256*256的一块surface对应各个cell,一开始该surface对应的z-buffer都是0,然后我们根据视点选择附近的一些occluder,可以选择上百个,(这是比object-space方法好的一点,一般的object-space算法只能是用少量的occluder),将视点与occluder形成的shadow volume以正投影视角(从天空上往地面的方向正投影)渲染在我们的surface上,这样surface对应的z-buffer上就留下了该shadow volume的高度,多个shadow volume的影响只要将他们都渲染到该suface上就可以得到,而且这种渲染可以使用硬件加速,所以可以使用许多occluder.最后对于每个cell的可见性判断,只要比较cell的高度和surface中对应的点的z-buffer的高度就可以判断出来了。
  这里还有一点需要改进的是,直接读取z-buffer是非常慢的,所以必须用个比较好的办法,将这种信息转换到surface buffer上,将surface buffer的数据拷贝到系统内存中的代价要低很多。
  具体做法如下:一开始surface buffer全部清0,对应的z-buffer设置为各个cell的高度。然后关闭z-buffer check和write,现将view frustum以颜色1渲染到surface buffer上,打开z-buffer check,用颜色0渲染shadow volume,最后将surface buffer拷贝到系统内存,数据为1的地方就是可见的cell。

  这种方法对于2.5d的城市来说确实是个好办法,不过他也有很多限制,比如对occluder的限制,你可能不得不为此专门写一个编辑器。对于其他全3d的复杂场景,这种方法也不行了。

  介绍了这些run-time的方法,我们可以看一下很多preprocess的方法,在run-time的时候计算可见性,对于一个相当复杂的场景来说,代价确实非常高。而事先计算好可见性的一些方法却可以取得非常好的效果。这种方法放弃了计算point to cell的可见性,转而计算cell to cell的可见性,这样虽然增加了可见部分,把一些不可见的cell也送入pipeline处理,但是preprocess却不用占用run-time的时间,这一节省大大提高了效率,因为在很多最坏的情况下,特别是在处理复杂场景的时候比起run-time就非常具有优势。基本的做法是计算出在每个cell中任何一个视点可能看到的其他cell的集合,也叫做PVS。运行的时候只要将pvs中的cell同时又处于view frustum中的cell绘制出来就可以了。然而如何计算出好的pvs却是一件非常复杂的事情。

  每个人也有不同的方法,具些简单的例子如下:
  1.在portal引擎适用的环境中,利用portal间形成的全影半影来计算pvs
  2.在cell的附近,选择一些occluder,然后不断的与周围的某些occluder形成一些virtual occluder(可以这挡住一些比较大的范围),然后再用这些virtual occluder去计算对其他cell的可见性。
  3.有一种针对2.5d的城市环境的pvs算法,对occluder也仅限于垂直于地面的rectangle,基本计算都是在进行2d空间的visibility计算,只在需要的时候才进行高度的检测。还有其他的一些算法,感觉都非常的复杂,我也还没有完全搞清楚,就不在这里乱说了

Culling技术的一些介绍相关推荐

  1. 本科计算机科学与技术专业物理,中国工程物理研究院职工工学院计算机科学与技术(本科)专业介绍...

    中国工程物理研究院职工工学院计算机科学与技术(本科)专业介绍 本专业培养具有良好科学素养,系统掌握计算机硬件.软件与应用的基本理论.技能,具有研究和开发计算机系统能力的高级应用型人才.专业核心课程:C ...

  2. AI开发者大会之计算机视觉技术实践与应用:2020年7月3日《如何利用计算机视觉增加便利店连锁每日销售额》、《基于图像 / 视频的人脸和人体分析基础技术及其应用介绍》

    AI开发者大会之计算机视觉技术实践与应用:2020年7月3日<如何利用计算机视觉增加便利店连锁每日销售额>.<基于图像 / 视频的人脸和人体分析基础技术及其应用介绍>.< ...

  3. 电气技术应用和计算机应用,电气技术应用专业介绍-1.ppt

    (自我结构理论 Company Logo LOGO 电气技术应用专业介绍 主讲: 2017年4月24日 熟悉电气技术应用专业的就业方向 电气技术应用专业介绍 了解电气技术应用专业的培养目标 掌握电气技 ...

  4. 电子科技大学计算机应用技术专科段,2020年电子科技大学成都学院计算机应用技术(专科)专业介绍...

    摘要: 2020年电子科技大学成都学院计算机应用技术(专科)专业介绍为你介绍2020重庆中职学校专业有哪些由中职中专技校网小编收集和整理,信息仅考参考! 电子科技大学成都学院计算机应用技... 202 ...

  5. 生物识别技术是什么,生物识别技术的比较介绍

    所谓生物识别技术就是,通过计算机与光学.声学.生物传感器和生物统计学原理等高科技手段密切结合,利用人体固有的生理特性,(如指纹.脸象.虹膜等)和行为特征(如笔迹.声音.步态等)来进行个人身份的鉴定.生 ...

  6. 【深入理解TcaplusDB技术】详细介绍TDR表数据类型

    [深入理解TcaplusDB技术]详细介绍TDR表数据类型 数据类型 基本数据类型 目前对于C/C++/c#语言,支持的基本数据类型如下表所示: 类型名 分类 存储长度(字节) 取值范围 Byte 字 ...

  7. 大前端CPU优化技术--NEON指令介绍

    前言 ARM NEON 可以提升音视频,图像,计算机视觉等计算密集型程序的性能,在上一篇大前端CPU优化技术--NEON技术的介绍中,我们知道一些编译器可以将 C/C++ 代码自动转换为 NEON 指 ...

  8. 云计算基础技术及解决方案介绍 - ZCCT考试

    文章目录 写在开头的话 云计算基础技术及解决方案介绍 00. 云计算的定义与特点 0.1 云计算概念定义 0.2 云计算交付方式分类 0.3 云计算服务分类 01. 资源池化技术 1.1 服务器虚拟化 ...

  9. 计算机科学与技术0775,0775 计算机科学与技术学硕专业介绍

    计算机专业如今竞争日趋激烈,考题形式多样涵盖的内容较多.数据结构.计算机网络.计算机原理.操作系统.C语言.C++.数据库.软件工程.程序设计)科目任选,题目自拟.0775考试科目中业务课哟可以设置为 ...

最新文章

  1. Linux环境进程间通信(二): 信号--转载
  2. wxWidgets:wxCloseEvent类用法
  3. 软件工程中的所有内聚类型【吐血整理,附带排名!】
  4. 使用simple transformation查找xml file内某个节点的attribute是否存在指定value
  5. CF1146F - Leaf Partition(树形dp)
  6. hive的metatable学习
  7. I2S和PCM区别(二十)
  8. zuul业务检查相关模块
  9. python 成语库_Python“Every Other Element”成语
  10. 告别巴蒂和你的年少时代--当Batigol成为永恒
  11. 图像处理软件ImageJ介绍与下载链接
  12. myqq框架 python插件
  13. WinCE 下鼠标键盘驱动分析
  14. Java常用英文单词
  15. CSS3构建一个正方体
  16. hdu 1203 (01背包,灵活运用)
  17. 现代软件工程 第一章 【概论】练习与讨论 王旭阳(2,3,4)
  18. python输出被五整除的数_Python程序打印给定数字的所有被3和5整除的数字
  19. solr的copyFeild用法(改变各个feild的权重,修改打分结果)-注意!
  20. A - 简单密码(C语言)

热门文章

  1. 暗影精灵2pro装Linux系统,暗影精灵2不支持linux双系统吗?
  2. 1+x证书Web前端开发HTML+CSS专项练习测试题(八)
  3. 《深度学习》/《Deep Learning》——深度学习圣经的读书笔记
  4. win7利用pycharm代码连接夜神模拟器运行appium,被杀进程怎么办
  5. 剑网3官方(内置)宏语法说明---(转自令狐志超帖子)
  6. 从Mac的GUID分区谈起
  7. 蓝牙也宽带 诺基亚3230蓝牙共享宽带教程(内网用户设置或网关无响应的解决)
  8. K8s-kubectl远程管理集群
  9. 崩坏3桌面版怎么更换服务器,崩坏3桌面版安装步骤介绍_崩坏3桌面版安装指南_玩游戏网...
  10. android显示视频预览