由于现在我们已经从光照预计算中排除了合适的对象物体,我们可以进行减少剩余光照图表数量的工作了。
因为生成光照图表(Charts)是为了包裹静态网格渲染器(Static Mesh Renderer)的光照贴图的UV坐标,所以一个对象所需要光照图表的数量很大程度上取决于物体需要展开的UV Shell(一些片)数量。这就涉及到UV展开的问题,它需要保持几何面上贴图纹素扭曲度与所需足够覆盖贴图Shell数量之间的平衡。
Unity没有我们的介入,它复杂的展开算法也将经常会得到很好的结果;然而有些时候需要提供给我们一点指导,这对于我们理解自动展开算法背后的理论过程是很重要的。
考虑下面的阐述:
在上面的图片中,我们展示了三个不同的例子关于一个对象物体上的UV是怎么被映射或展开的。
在第一张图片中,我们可以看到一个大部分没有扭曲变形的结果。我们所使用的带有格子图案的纹理贴图以这种方式被映射:贴图的每一块在它所在的那一面都保持正方的形状。试想一下这个棋盘纹理贴图是一个光照贴图(一个光照应用于对象物体的图片),我们将会得到一个看上去视觉上正确并且没有扭曲的结果。然而,我们需要6个UV shell 去得到这个覆盖范围。结论就是,通过使用Unity的PRGI系统,我们将会得到六张光照图表。不管对象物体的尺寸大小,每个光照图表将会需要一个4*4的最小纹素,这意味着不管分辨率是多少这个对象物体都将会使用至少96个纹素。
在第二张图片中,我们有了一个不同的问题。对象物体的UV纹理坐标已经被映射,以及至于我们有了一个完整的覆盖所有面的UV shell。尽管就需要覆盖对象物体的光照图表的数量而言这将会是最佳的形式,但是它视觉上的效果已经被严重的扭曲了。我们很可能看到应用到物体表面的纹理贴图是扭曲的,对象物体上的各个表面在UV纹理空间也是重叠的 - 意味着如果我们引用了一张光照贴图,对象物体一面的光照可能会错误投射到相反面上。这种展开对象物体UV的方法明显将不会给我们一个可以接受的结果。
第三张图片展示了一种展开UV理想的例子。我们有一个没有扭曲的结果:我们的棋盘纹理贴图的每一片在它所在的那一面都保持着正方的形状。我们还成功地用一张UV Shell覆盖了对象物体的所有面。这是通过连接或缝合在模型上对应的邻近的几何边缘相匹配的UV边缘来实现的。
我们如果从编程的角度思考这个问题,在获得一个理想的展开UV过程中,我们都做了些什么。首先,为了在对象物体上生成独立的Shell,我们通过正交投影(Orthogonal Projection)让UV贴图在物体上。然后分析哪些Shell和物体的边缘有相连关系。一旦找到这些边缘,就把UV Shell的内容移进去并与相邻的Shell缝合起来。这就是Unity用静态几何自动地展开UV的算法所做的事情。
将光照图表可视化(Visualising Charts)
在优化我们的UV展开方式以及光照贴图的图表之前,我们需要一种将它们在Editor中可视化的方法。光照图表产生于mesh导入管线的UV展开阶段。对于PRGI来说,这些光照图表之后会在预计算过程的几何阶段被打包进atlasses图集中。这时为了确保它们不会重叠。一旦预计算的几何阶段完成并且可视化数据被保存后,我们就能预览我们的光照图表了。
如果你是一个团队的一部分,使用版本控制(Version Control)进行工作,请注意光照图表的信息只会在本地进行缓存。这意味着在各种诊断绘制模式可用之前,在你的机器上必须要执行一次预计算。
一种快速地显示你的光照图表的方法是在Scene视图下使用UV Charts 绘制模式。
* 在Scene 视图的左上角,使用 Draw Mode下来菜单去选择UV Charts选项。
通过使用这种模式,光照图表能够以不同颜色区域覆盖显示在一个代表着对应光照贴图分辨率的棋盘网格纹理贴图上。如果你想开启Auto 模式(Window>Lighting>Auto), 改变UV展开参数将会被自动地计算并且Scene 视图将会随着结果而更新。
场景较为复杂时,从场景视图中有可能会漏看光照图表。这时候我们可以在Lighting视图中使用预览模式查看单个物体使用的所有光照图表。这样可以帮我们更精确地评估这些物体的UV展开结果,有助于降低光照图表的数量。具体操作如下:
* 打开Lighting界面(Window > Lighting),选择Object标签页
* 从层级视图(Hierarchy)中选择要查看的对象。
* 查看Lighting界面的预览视图,从最上方的下拉列表中选择Charting模式。
对象使用的光照图数量会以不同颜色的方块叠放在对应的浅蓝色UV坐标上。
UV展开参数说明
下面我们一起来看一下几个有助于优化UV展开的设置,所有的设置都是针对单一对象,具体设置方法如下:
* 打开Lighting窗口(Window>Lighting)并选择Object标签页.
* 在Hierarchy窗口选择我们想要看到的物体。
自动最大UV距离(Auto UV Max Distance)
Unity的UV展开算法尝试通过移动shell以及缝合UV边缘这两种方式一起来简化光照贴图的UV。如果shell在由 Auto UV Max Distance 属性定义的距离范围内,那么UV shell 才会被考虑。这个经历范围是在Unity世界空间单位下所定义的。请记住在我们的教学场景中,我们假设一个单位等于1米。
在许多情况下,默认值为0.5个单位长度将会产生比较好的效果。尤其对于面比较大的大型对象物体来说,提高这个值得设置是很有必要的。这是为了防止本来应该被缝合的UV被UV缝合算法排除在外。
增加Auto UV Max Distance这个值将会减少所选对象物体所需的光照图表的数量。在有明显的光照贴图纹素被拉伸的情况下,以及需要生成更多的光照图表进行覆盖的情况下,降低这个值是很有用的。在UV Charts场景绘制模式通过使用覆盖的棋盘网格图,这些改变的结果很容易被评估。寻找到合适的平衡点通常需要一些尝试。
自动最大UV角度(Auto UV Max Angle)
光照UV shell 缝合的计算会以相应mesh邻面之间的角度为基础。Auto UV Max Angle定义共享一个UV边缘的面之间允许的最大角度,并使用内角计算。如果背面之间的角度大于此值,这些UV shell将不会被缝合。
提高这个值将更有可能促使Unity的UV展开算法合并了光照UV图。因此调节Auto UV Max Angle 这个值对于减少所选物体需要的光照图表的数量是一种很好的方式。然而,如果设得太大,有时会出现贴图被拉伸的情况。降低 Auto UV Max Angle 这个值将会使得UV展开算法合并UV边缘的可能性变小,将会生成更多的光照图表但是拉伸的情况会减少。再一次说明,在UV Charts场景绘制模式通过使用覆盖的棋盘网格图,对于评估我们所使用的合适的值是一种很好的方法。
预存储UV(Preserve UVs)
在一些情况下,通过使用auto unwrapper不太可能获得一种理想的展开效果。我们可能会得到这样的结果:过多的光照图表或者在我们的光照贴图上产生了严重的扭曲(当在GI Charts绘制模式下进行可视化拉伸检查)。在这些情况下,在我们的模型文件中的UV01通道中去手动地创建UV可能是很有必要的。这必须要在其它工具中完成。
如果出现这种情况,可以在Preserve UVs选项让Unity的UV展开算法强制预存模型UV01通道定义的UV Shell。
要注意的是,这些Shell会被重新打包以节省光照贴图空间,它们会被单独解开并预存储,而非仅仅记录光照贴图内的坐标信息。
使用这个功能时必须小心,当指定的光照UV贴图包含大量的UV Shell时,这个功能可能会让预计算的时间加长,这时因为跳过了由Unity 中 auto unwrapper 提供的UV合并步骤,并且我们手动的UV布局会被预存储。记住最好的结果是尽可能的降低UV Shell,因此这样会减少光照图表的数量,同时将UV贴图保持在可接受的拉伸范围内。
忽略法线(Ignore Normals)
在某些情况下,网格导入器可能会拆分几何体,这也会影响到光照图表的数量。例如,如果某个网格有非常多的三角面,Unity可以为了性能将它分割成几个独立的子网格。通常这么做是为了符合特定的硬件需求,比如为了减少每个Draw Call中的三角面数量。拆分通常发生在相邻的网格面之间法向角度有较大变化的区域,比如锐角边(Hard Edges)。这样拆分网格的方式会在模型导入流程中执行。在此过程中,光照图表可能会被拆分,因为光照图表中的边可能会被分开,导致生成多个shell,而这又会产生额外的光照图表。
有时通过这种方式对光照图进行拆分并不理想,得到的结果会增加光照图数量并加长预计算的时间,还有可能在照明的接缝处造成不必要的视觉假象。在这种情况下,启用Ignore Normals选项有助于防止光照图在预计算的时候被拆分开来。
请注意,这个选项仅对预计算实时光照(PRGI)有影响,物件被拆分的网格仍然会被保留以用于其它用途。
大场景迅速迭代(Faster iteration in larger Scenes)
复杂的场景可以包含成百甚至上千的静态对象物体。为这些对象物体生成光照图表atlases图集可导致光照预计算变得缓慢并且会对我们的场景迭代速度产生负面的影响。
当对物体进行UV展开实验时,将你想要实验的对象物体隔离到一个空场景中,这样我们可以用最短的预计算时间来快速地迭代。当我们所决定使用的UV展开设置之后就可以被回收并且可应用于我们原来场景中同类型的其他对象物体。当为一个场景准备光照时以这种方式开展工作可以大大节省时间。具体操作如下:
* 打开包含在例子工程中的LightingTutorialStart场景。
* 在Hierarchy窗口中选择其中一个叫做HouseBig02的对象物体。这些对象物体在Environment>Structures>Houses下已经被分组。
* 通过按下Ctrl+C(Cmd+C on Mac)粘贴这个对象物体到剪切板.
* 通过按下Ctrl+N创建一个新的场景(Cmd+N on Mac)。
* 如果提示你保存你的更改,如果你对你当前的场景进展比较满意选择Yes,如果你不想保存,选择No
* 在先创建的场景中,通过按下Ctrl+V(Cmd+V on Mac) 从剪切板中粘贴 HouseBig02。
* 打开 Lighting 窗口 (Window>Lighting)然后选择Scene标签页。
* 通过开启Auto选项框来启动自动预计算模式。
* 现在选择 Object 标签页。
*在左上角的Object标签页,从下拉菜单选择 Charting。
* 拉大预览视图区域来查看对象UV是怎么被展开的。