使用光照探针实现静态光照

来源: Unity官方平台

在Unity 2019.2中,我们移除了Lightmap Static标识,使用Contribute to GI取而代之。

在Unity 2019.2中,开发者可以选择从光照贴图或光照探针接收全局光照,这个看似很小的改动将给场景光照的烘焙性能和质量带来巨大影响。


光照贴图和光照探针

全局光照通过一系列复杂的计算,来计算光线从光源射出后在物体表面间的弹射。通常在运行时实现精准的模拟,所使用的计算开销较大。为了实现最佳光照质量,常见的解决方法是将这些繁重的计算转移到编辑模式中的预计算步骤中去完成。

要实现该方法,需要确保场景中的多个对象和光源位置保持在相对固定的位置,不会发生变形、旋转、或者改变外表属性。有了这些前提条件,光线便可使用光照贴图技术进行计算。

为了标记这些对象,Unity提供了Lightmap Static标识。它表示只有静态对象才会使用光照贴图,但静态光照贴图只是在场景存储全局光照的多种方法之一,而且存在有一定的缺陷。

当使用光照贴图来实现全局光照时,非静态或动态对象无法影响全局光照,因为它们违背了静态这个前提。如果为移动的对象计算全局光照,光照只会在该对象的起始位置上生效,这就是传统光照贴图的主要局限问题。

动态对象仍然能够通过光照探针接收到来自其它静态对象生成的全局光照。光照探针是空间中的一个个位置点,它能够储存来自所有方向的光线采样,这类光照数据会被编码为名叫“球谐函数”的特殊值。

在运行时,动态对象可以在世界中移动时从附近的光照探针接收到光照数据。这项功能使动态对象能够正确接收到局部光照,从而正确地融入周围的光照条件。

从技术上来说,静态对象完全可以使用光照探针取代光照贴图,所以为什么要使用光照贴图呢?

纹素成本

需要制作光照贴图的对象必须先进行展开,并在光照贴图中预留部分空间。根据分辨率,每个投射进光照贴图的对象会保留特定大小的纹素。

如下图所示,在每个空间单元有1个纹素的光照贴图分辨率中,大小为1x1x1的单元方块会为每个面保留1个纹素,因此总共有6个纹素。在每个纹素上,光照贴图需要计算照射到纹素世界位置的光线。


计算过程是首先投射射线,让这些射线在场景中弹射,直到找到光源。使用的纹素越多,结果的计算量越大。当场景中有许多小型对象时,计算量会大幅增加。

实际上,这类对象的展开,标记及光照贴图制作正是导致烘焙失败或烘焙耗时较长的最常见原因。

石块,碎片等小型对象或电线,杆子等较细的对象很容易产生“无用纹素”。虽然这些纹素不会给对象的整体外观有太大影响,但却增加了计算时间,占据不少光照贴图空间。

较细的对象经常产生宽度仅有1-2个像素的展开结果,因此对整体外观的影响很小。类似的,根据对象在屏幕上的大小,小型对象经常在光照贴图产生许多对最终效果影响不大的纹素。

这样造成的结果是:在视觉效果上影响不大的纹素耗费了大量计算时间,并增加了所需的光照贴图空间量。

如下图所示,对于小型对象,我们可以使用光照探针。


针对生成光照贴图时间的优化方法之一是将这些小型对象设置为非静态,将其移出光照贴图计算,以此来减少需要计算的光照贴图纹素数量。

但在部分情况下,这些对象对场景光照会有很大影响,例如:非常明亮的彩色对象,或者带有发光材质的对象。如果这些对象不设为光照贴图静态,它们无法对场景的全局光照产生影响,也就不会对预期光照结果产生影响。

因此在处理这类对象时,我们面临两个不同的选择:

为这些对象添加光照贴图,使其能够对场景产生影响,而代价是增加烘焙时间,浪费光照贴图的空间。

放弃这些对象的影响,但会降低整体外观和全局光照的质量。

我们要如何解决这个两难问题呢?

使用光照探针

在Unity 2019.2中,我们添加了一个功能,使得对象能够在接收光照探针的全局光照的同时,对场景施加光照的影响。我们可以在检视窗口中Mesh Renderer组件新增的下拉菜单中启用该功能。

下图为新增的Contribute Global Illumination和Receive Global Illumination选项。


我们可以在此选项中,通过为Receive Global Illumination选择Lightmaps,让网格渲染器从光照贴图接收全局光照,在Unity 2019.2前,该选项是用于静态对象的唯一选项。

我们也可以在此选择Light Probes,从光照探针接收全局光照,在Unity 2019.2前,这是用于动态对象的唯一选项。

如果对象启用Contribute Global Illumination标识,该对象会包含在光照贴图的全局光照计算之中。虽然前提依旧是对象要一直处于静态,但现在我们可以根据具体的光照保真度要求,直接指定对象是使用光照探针还是光照贴图。

如果对象勾选Contribute Global Illumination,并选择从光照探针接收全局光照,该对象仍会对周围环境产生影响。例如:一个高大的路灯会根据周围光照贴图的计算来投射阴影,同时路灯上的发光材质也会照亮周围的场景。

如何使用

通过使用这项新功能,我们可以在Unity中简单直接地优化麻烦的细小对象:只需将Mesh Renderer组件中的Receive Global Illumination字段选为Light Probes即可。

设置完后,指定的对象便不会在光照贴图中占用空间,而相应的纹素也不会再产生不必要的计算。

光照探针另一个关键的优点是它们不需要合适的UV来工作,从而节省许多UV展开时间。如果有使用光照探针时效果不错的动态对象,而且它从不移动,旋转或发生变化,我们可以给它勾选Contribute Global Illumination标识。

这样,该对象便能在不增加烘焙时间的情况下,影响周围添加了光照贴图的对象。从而我们可以大幅提高效率,减少内存的使用量。

小结

通过这项新功能,动态或非静态对象能够使用光照探针来接收光照。你可以决定全局光照计算中的对象从光照探针或光照贴图中接收间接光照,并减少光照贴图中的纹素使用量。

总之,这项改变将大幅减少光照贴图的计算时间,降低内存使用,提升运行时的性能。

本文转自: Unity官方平台,转载此文目的在于传递更多信息,版权归原作者所有。

最新文章