http://blogs.unity3d.com/2013/12/02/occlusion-culling-in-unity-4-3-the-basics/
这篇博文由Umbra Software的Jasin Bushnaief所写,旨在解释Unity4.3遮挡剔除的更新。
Unity4.3包含了大量的改进。全新的子系统之一包括遮挡剔除。不但简化了界面,剔除运行本身也改写了,还添加了一些列的新功能。
在这个系列的三篇博文里,我将介绍Unity4.3的新遮挡剔除系统的使用方法。第一篇讲完成遮挡剔除以及使用用户界面的基本方法;第二篇主要讲有效遮挡剔除的最佳实践;第三篇讲一些常见问题以及解决方案。
先从基本的开始讲起。遮挡剔除是指消除隐藏在其他对象中所有对象。这意味着在隐藏的东西上不会浪费资源,让游戏运行更快更美观。在Unity里,遮挡剔除依靠中间件组件:Umbra,由Umbra Software开发。Unity中控制Umbra的UI,在Window -> Occlusion Culling,Bake Tab下。
Umbra如何工作
Umbra的遮挡剔除过程大致可以分为两个不同的阶段。在编辑器里,Umbra处理游戏场景,游戏运行时使可见查询在播放器中执行。所以第一,Umbra需要把游戏场景作为输入,并bake成一种轻量级数据结构。Bake的过程中,Umbra首先把场景解构成voxel,然后把voxel组成cell,并将其与portal结合。这个数据,除了一些其他的重要片段,被称为Unity的遮挡数据。
运行时,Umbra执行软件入口格栅化为深度缓冲,与可被检测的对象可见性相反。实际上,Unity给了Umbra一个相机位,Umbra回馈为可见对象 的列表。可见性查询通常是保守的,意味着不会返回假阴性。另一方面,有些对象被Umbra视为可见,即使在现实中明显不是。
注意到这一点很重要,这个系统类似于以前的Unity版本,整个系统已经基本被重写了,很多地方都变得更好,无论是内部还是外部。
如何使用Umbra
获得遮挡剔除的最佳实践有几个明显的顾虑。理想的,你想尽快得到最小限度保守的结果。然而,关系到权衡。越想要精确,就越要产生更高分辨率的数据。运行时 遍历高分辨率数据很慢,产生较慢的遮挡剔除。如果遮挡剔除比它剔除保存的需要更多帧时间,这明显没有意义嘛。另一方面,非常快速的剔除也没有什么帮助,除 非只有几个对象被剔除。所以这是一个权衡的问题。
Umbra权衡的方式是定义一对bake参数。参数决定bake过程应该期待什么样的输入类型,产生什么样的数据。在运行时,使用Umbra很简单,如果你已经bake了遮挡数据,并且相机有在Inspector启用遮挡剔除,Unity就会自动使用Umbra。
最小的孔
输入由最小的孔参数控制。当三维像素化遮挡几何,最小孔映射几乎直接到体素尺寸。这意味着如果几何体包含你意料之中的孔、缺口或裂纹,使用比这些还小的最 小的孔是个不错的想法。另一方面,很多时候,几何包含许多意外的裂纹,这些是你不希望看到的。一个合理的提速分辨率将修补这些。它或许把最小孔作为烘焙的 “输入分辨率”。
注意设置最小孔为小值意味着烘焙会慢的令人无法接受,或者占用大量的编辑器内存。在某些罕见的情况下,它甚至会由于烘焙不足导致烘焙失败。使用一个较大的 值则会快很多,并且内存友好,它可能导致Umbra识破不了壁炉或栅栏之类的东西。所以更大并不一定总是好的。通常,一个没有不可见错误的尽可能大的最小 孔是可取的。实际上我们发现5cm到50cm对大多数游戏来说效果非常好。Unity的默认值是25cm,这是一个很好的起点。
最小遮挡
最小孔主要处理输入几何体的类型,最小遮挡决定产生什么样的输出数据。本质上说,你可以把最小遮挡看做数据的输出分辨率。值越大,运行时执行遮挡剔除的速 度就越快,但以增加守恒性(误报)为代价。值越小,产生的结果越精确,但是更加耗费CPU时间。显然高分辨率数据将意味着更大的遮挡数据规模。
较小的值意味着遮挡数据里捕获了非常好的特性。Hood之下,这直接映射到Umbra建立多大的cell。许多小的cell意味着它们之间有很多小的入口,自然,这将花费更多来格栅大量的小入口,反之亦然。
改变最小遮挡的效果可以在下图中看出来,请注意如何深度缓冲,这基本上是Unbra看到的,随着最小遮挡的增大细节逐渐损失。
在大多数游戏里,保持最小遮挡比player稍大,所以在几米范围之内是不错的。所以2-6米之间是可以的,只要游戏规模不是特别小或特别大。Unity的默认值是5.
背面阈值
也许最难掌握的参数是背面阈值,在大多情况下不需要改变,有些情况可能会派上用场,帮助了解它如何影响数据的产生。
首先,注意参数存在的目的只有一个:遮挡数据大小的优化。这意味着入伙遮挡数据没有问题,你只需无视背面阈值。第二,该值被译为百分比的形式,所以90意味着90%,等等。
那么背面阈值的价值所在是什么?想象一个典型的场景,由实体对象组成,此外,还可能有正常向上的地形网格。这样一个场景,相机应该在哪里呢?肯定不在地形 下面。你肯定也不想相机在实体对象里面。这些无效的地方也是你倾向于看的背向三角形。所以在很多情况下,在场景的任何地方做假设是安全的,从相机看到了很 多背向三角形,是无效的一个,意味着游戏中的相机永远不会结束在这些位置。
背面阈值有助于利用这一事实的优势。通过定义从任何有效相机位置可以看到多少背向几何极限,Umbra可以剥去超过这个阈值数据的所有位置。这在事件中如 何工作只要通过拍摄光线在所有cell做随机抽样,然后看那些线有多少击中背向三角形。如果阈值超过,数据会丢弃cell。有一点要注意:只有遮挡有助于 背面测试,并且遮挡面不承担任何相关性。100的值完全禁用背面测试。
所以,如果背面遮挡若设为70,例如,对Umbra来说意味着场景的所有位置,超过70%的可见遮挡结合没有面对相机,会被遮挡数据剥离,因为现实中相机 绝不会在那里结束。自然不需要从地形之下正确执行遮挡剔除,例如,无论如何相机都不会在那里。在某些情况下,这可能产生相当重要的数据大小存储。
从遮挡数据中剥除这些位置意味着遮挡剔除在这些地方未定义。“未定义”,在这里意味着结果可能是正确的、不正确的(非常随机),或者返回错误。在错误的情况下,所有的对象都是简单的视锥剔除。
当然在某些情况下,恰好是在有效的相机位置有一些数量的背向几何。或许有一个片面的网格,可能错误地被标记成遮挡。如果是一个大的,或许会触发附近区域的背向测试触发器,造成剔除错误。这就是Unity中背面阈值的默认值为100的原因,意味着该功能是默认禁用的。
随意实验参数。试着将值减少到90,例如放弃地形下的大量数据。看看在遮挡数据规模上是否有明显的效果。如果你愿意,你甚至可以把值设置的更小。记住这只是你自己的冒险尝试。如果你开始渲染,把值设置回100,看看是否能解决问题。
未完待续……
在下一篇博客中,我将给出一些最佳实践以及获得最佳遮挡剔除的建议。同时,请访问www.umbrasoftware.com获得Umbra的相关信息。