Occlusion Culling in Unity 4.3: Best Practices(中文翻译在后)
[size=0.875em]The following blog post was written by Jasin Bushnaief of Umbra Softwareto explain the updates to occlusion culling in Unity Pro 4.3. [size=0.875em]This is the second post in a three-post series. In the previous post, I discussed how the new occlusion culling system works in Unity 4.3. I went over the basic usage and parameters that you need to know in order to get the best out of occlusion culling. In case you missed it, check it out here. [size=0.875em]This post gives you a list of general recommendations and tips that should help you get the best results out of occlusion culling. Good quality occlusion[size=0.875em]It may seem obvious, but of course the first thing to make sure is that your scene actually contains meaningful occlusion. Moreover, the occlusion should preferably consist of good, large occluders if possible, as opposed to fine details that only accumulate as occluders when looking at from a certain angle. Umbra will generally not be able to perform occluder fusion, so even if your lush forest with lots of foliage will occlude something behind it, it will do so only once the individual occluders are “accumulated”. So in this sense, the trees and forests in general will be pretty bad occluders from Umbra’s point of view. On the other hand, a mountain is a good occluder and Umbra will certainly be able to capture it into the occlusion data as expected. [size=0.875em] Object flags[size=0.875em]There are two main types of objects Umbra cares about: occluders and occludees. The former are just geometry and Umbra treats them basically as a single, solid model. The latter are the ones whose visibility Umbra actually tests using the occlusion data. Occluders consist of pretty much all geometry that have the “Occluder static” flag set, and unsurprisingly, occludees that have the “Occludee static” flag, respectively. [size=0.875em]As a rule of thumb and by default, you can and should set most if not all your renderers as occludees in order for Umbra to cull them. Also by default, most of your static renderers can be occluders as well. Just make sure that if your renderer is non-opaque, it shouldn’t be an occluder either. (Unity will actually issue a warning if this is the case.) This naturally includes transparent objects and such. [size=0.875em]But also, if your object contains very small holes (consider e.g. a cheese grater or a bushy plant) that you wish to see through, but reducing the value of smallest hole globally doesn’t make sense (see the previous post as to why), simply removing the occluder flag from the renderer is the correct thing to do. [size=0.875em]Furthermore, because occluders are considered solid, correct culling can typically be guaranteed if the camera doesn’t intersect an occluder. This means that if e.g. the collision system cannot prevent the camera from flying inside an occluder, you should probably remove the occluder flag in order to get meaningful results. Object granularity[size=0.875em]Given the fact that Umbra does object-level occlusion culling, it doesn’t make a whole lot of sense to have objects of several kilometers in size. Such massive objects are very hard to cull, as some part of the object is almost always visible, especially combined with Umbra’s conservative culling. So, splitting up e.g. the terrain into multiple patches is typically a good idea, unless you want the entire terrain to always be visible. [size=0.875em]In terms of occlusion culling, typically the best object subdivision is a natural one, meaning that naturally distinct objects should probably kept separate in culling as well. So chunking objects too aggressively typically doesn’t help. One should group only objects that are similar in terms of visibility. On the other hand, too fine-grained subdivision may introduce some unnecessary per-object overhead. In reality, this becomes a problem only once there are tens of thousands of occludees in the scene. [size=0.875em]Maybe it should be emphasized that only the object subdivision of occludees matters. Occluders are considered to be a single big bowl of polygon soup anyway. Watertight models[size=0.875em]In the previous post, I briefly described how Umbra first voxelizes the occluding geometry, groups these voxels into cells and then connects the cells with portals. In the process, Umbra is always conservative, meaning that in various cases Umbra considers the occluders slightly smaller than what they are in reality, or conversely, the empty areas slightly larger. [size=0.875em]This means that if there happens to be an unintentional hole in your occluding geometry, one which rather than getting patched up is retained by voxelization, there’s a good chance it’ll become somewhat magnified in the final output data. This may lead to surprising “leaks” in occlusion. The camera may be looking at a seemingly solid wall, but things behind the wall don’t get occluded because there’s some unnoticeably small crack somewhere. [size=0.875em]So, while voxelization does patch a lot of unintentional cracks and gaps in the occluding geometry, it’s still highly important to try to model the geometry as water-tightly as possible. In the next post, I’ll describe the Visibility Lines visualization which may help you debug these kinds of issues. Finding the right parameter values[size=0.875em]Admittedly the hardest part of using Umbra is finding the right parameter values. The default values in Unity do a good job as a starting point, assuming that one Unity unit maps into one meter in your game, and the game’s scale is “human-like” (e.g. not modeled on a molecular level, nor is your typical object a planet or a gigantic killer-mech-robot). [size=0.875em]A good rule of thumb is to start with relatively large values and work your way down. In case of smallest hole, for instance, the larger value you can use, the swifter is the bake process. Thus, you should tune it down only if/when you start experiencing culling artifacts, i.e. false negatives. Similarly, starting with a relatively large value forsmallest occluder typically makes sense. [size=0.875em]Then you can start adjusting it downward and see how Umbra culls better. Stop when culling starts taking up too much time and/or the occlusion data becomes too large. [size=0.875em]As for backface threshold, start with 100. If your occlusion data is too large, or if you happen to get weird results when the camera is very, very close or possibly even intersects an occluder, try using 90 or even a smaller value. More on this in the next post. To be continued…[size=0.875em] 这是本系列文章的第二篇,之前的文章Unity4.3 遮挡剔除:基本知识,我们讨论过Unity 4.3中的新型遮挡剔除系统(occlusion culling system)如何运作,我重新列出了一些基础的使用方法和参数,有助于你更好的使用这种新系统。为方便使用,你可以在这里下载。 下面将逐步介绍,针对更好使用遮挡剔除系统的一般性建议以技巧。 优质遮挡(Good quality occlusion) 显然,首先要保证屏幕上的遮挡是有意义的,而且,应该优先遮挡那些优质、大型的物体,让观测者处在任一角度时,都不必重复优化遮光物的精细度。全影技术通常不能很好的实现景物融合,因此,即使你所拍摄的森林很茂密,有很多树叶会遮挡它背后的东西,但还是会漏过一些光线。从这一层面来讲,树和森林从全影技术的角度而言,算是较差的遮光物。相反,山是一种良好的遮光物,所以能让全影技术获取预期的遮挡数据(occlusion data)。 物体标识(Object flags) 目前,物体全影技术需要考虑两方面因素:遮光物(occluder)和所遮挡的物体(occludee)。前者定义于几何学的角度,全影技术会将它们构建成单一、稳定的模型;后者定义于可见性的角度,全影技术通常会通过遮挡数据对其进行测试。从几何学角度来讲,遮光物是由大量的带有“Occluder static”标识的设置组成的,而被遮挡物体的标识则是“Occludee static”。
一个经验法则,默认情况下,如果不是所有的渲染器作为被遮挡的物体,你最好预先设定好大多数配置,以便于在全影技术下可以自动剔除不必要的景物。同样,也是在默认的情况下,多数的静态渲染器(static renderers)都可以作为遮光物,只要确保你的渲染器不是透明的即可。 但是,如果物体的缝隙很小(像是浓密的植物),你又想透过它们看到景物,只是减小这些缝隙的最小值是没有用的,而应该从渲染器中移除这些遮挡标识(occluder flag)。 此外,因为遮挡物通常是实心的,所以通常来讲,正确且典型的剔除方法应该是,让照相机与遮挡物之间不交叉。这就意味着,如果避碰系统(collision system)不能阻止照相机在遮挡物内部“穿行”的话,为了得到较理想效果,你应该人为移除相关遮挡标识。 对象粒度(Object granularity) 事实证明,全影技术是在对象层面上(object-level)进行遮挡删除,但对特别大的物体是不起作用的。想要遮挡尺寸特别大的物体非常麻烦,因为这些物体有些部分是可见的,因此,可以选择类似于测绘地形时的方法,即,将整块地分为多个部分进行测量。 利用遮挡剔除技术,分割物体最好的方法是尽量保持它的自然状态。所以,拍摄者应该利用可见度将相似的物体归为一组,另一方面,过于精细的画分可能会引入一些不必要的麻烦。事实上,只有在屏幕上出现数以万计的遮挡物时,这种情况才会引起麻烦。 水密模型(Watertight models) 事实上,全影技术的反应还是比较迟钝的,这就意味着,在不同的环境中,全影技术所得的遮挡物要比实物些许的小些,或者说,空白区域要更大些。 这意味着,如果恰好是在你的遮挡几何形状中,保留了一个未得到修补的、已被体素化(voxelization)的小孔,那它很有可能在最后的数据导出中被放大一定的比例,这有可能会导致一定的漏光现象。相机虽然对准一堵坚实的墙,但墙后面的东西没有得到足够的遮挡,因为不可避免的会存在一些小裂缝。 因此,当利用体素化修补了大量遮挡物上的缝隙时,尽可能的构建“水密模型”依旧十分重要。下一章,我将描述可见性线条(Visibility Lines)的视觉效应,也许就可以帮你解决上述问题。 找到最佳默认值(Finding the right parameter values) 事实上,使用全影技术最困难的部分是寻找合适的参数值。Unity中的默认值通常就可以作为起点,假设,将一个Unity地图融进游戏的中,采用仿真的游戏模式。 经验表明,可以先设定比较大的值,然后让它按照自己的方式工作。例如,处理最小的孔时,可以使用较大的值,来加速它的成型过程。因此,当你开始要遮挡物体的时候,应该逐渐缩小值。然后,你可以逐渐缩小值,了解全影技术是如何进行遮挡的。当遮挡占用太多的时间,或者是遮挡数据过多时,可以停止这种缩小操作。 至于隐性阈值(backface threshold),初值值设定为100。如果遮挡数据太大时,或者在相机位置过近,甚至与遮挡物相交时,恰巧得到错误的结果,你可以尝试将其设定成90或者是更小的值。更多的内容请看下节教程。 未完待续
|