Unity的光照烘焙技术(上)

2020/01 14 10:01

本文将分享Unity的技术美术李万里在Unite Shanghai 2019大会的演讲内容,他将深入浅出的带领你了解Unity的光照烘焙技术。

演讲内容

今天很高兴和大家分享我工作这么多年来对Unity光照的理解和认识。

首先我将介绍一些概念,然后慢慢的深入给大家讲解,如何使用Unity的Progressive工具去正确的烘焙光照以及设置一些光照。

为什么谈谈Unity光照呢?

因为我发现很多客户对Unity的光照烘焙技术了解都存在问题。他们认为Unity的光照不好,没有别的引擎效果好,或者存在其它的问题。但大家通过参加Unite 2019大会,看到了不少Unity高品质的一些画质。

本次演讲,我将主要给大家分享在Unity的内置渲染管线和轻量级渲染管线LWRP下,如何正确烘焙光照。

Unity的光照和烘焙是每个制作游戏的人都非常重视的,因为它的效果决定了游戏品质。

前些年,由于受困于性能限制,很多使用Unity开发的游戏是没有光照的,主要是靠手绘贴图。由于计算性能的提高和移动平台的高性能,现在我们可以制作出前几年主机平台上的游戏品质。

所以光照烘焙在游戏开发者领域是一个越来越重要的问题,这也是越来越多公司通过招聘技术美术来提升画质的重要原因。

Unity的光照基本上就是分三种:从早期的Enlighten到Progressive CPU,再到Progressive GPU,从发展轨迹可以看出,大家对光照还是偏向光线追踪算法,认为这是未来的发展方向。

因为Enlighten本身不是光线追踪算法,它是一种非常复杂的数学模型算法,而且对美术制作非常不友好,导致很多人使用Enlighten烘焙都效果不佳。

我们说了Unity光照,就不得不说Unity的光照技术。

主光源是:Directional Light、Area Light、Spot Light、Point Light。基本上是目前游戏开发的主流光照,Directional Light和Area Light是使用得最多的,其次是Spot Light常常用于人造光源和特效光源。

SkyLight是Unity很重要的一个功能,这也是很多人烘焙Unity光照最容易出问题的部分。Unity提供Procedural Skybox,这个Skybox基本上会贡献整体光照烘焙Lightmap的80%左右,所以如果不会使用SkyLight,烘培出来的贴图将效果很差。

最后是Light Probe和Reflection Probe,它们是用来提升一些特殊效果和优化性能的。

说到Unity的光照,我们不得不提到一点:Unity从Gamma空间过渡到线性空间,以及现在一直保留的Gamma空间的支持,是为了一些老的项目有版本升级的可持续性,但未来Gamma空间将被淘汰掉。

线性空间的优点是能够容纳更多亮度细节,不需要压缩亮部来提高暗部的效果,亮部的表现力更强,更接近真实的光照效果。由于当年OpenGL ES 2.0时代的整个计算能力有限,所以Gamma空间进行了一些压缩。

我们看一下上面这张图,这就是Procedural Skybox,它重要在哪儿呢?

因为它提供了光照。我们自然界中光照有两个非常重要的概念,一个概念是它有大气的厚度,大气厚度决定色散的情况,对光线的反映。

Sky Tint主要用来计算天空的染色情况,如果空气密度很高,整个天空又染上一些色,它对光线的反应情况。正常情况下,对地球的Sky Tint,只有沙尘暴时才会出现比较奇怪的效果,如果没有沙尘暴的情况下,地球的Sky Tint值比较接近灰度的颜色。

如果在制作异星题材的游戏的话,情况就不太一样,你可能要根据颜色的调整,让大气做一些吸收,这样折算出来的Sky Light会发生一些改变。

Ground基本上是Skybox在模拟地面对物体的影响,如果值很强会让地面失去立体感,计算时底部的光照会很强,导致天花板的区域变亮。所以这个值不要调得特别的高,基本上以灰度为主。

Exposure曝光度的值非常重要,它是天光的强度,基本上可以达到8或更高的倍数,它可以让整个天光变得更强,更强的结果是整个Skybox会非常强。好处是带来更多间接光的强度,但也会带来让受光比较多的地方产生过曝的问题,这是大家需要控制的。

关于Exposure曝光度,建议大家可以跟Atmosphere厚度的值一起调整。如果曝光度增强的时候,可以将大气密度提高,它会形成比较奇怪的现象。在大气足够密的情况下,曝光度很强,大气密度底部会对光线的吸收特别的强,会发生右侧图片发红的情况,这样会计算出一些接近于早晨、晚上的效果。

像左侧这张图,基本上它的大气密度值在1,Exposure值在3,而值在2是另一种效果,它的厚度值在2时,产生了色彩上的变化,这个变化是在模拟物理的效果。

Directional Light在移动游戏开发中常常用作太阳和月亮的首选光源,因为它能够覆盖整个场景,计算的时候非常节省性能。

直接光强度在线性空间下,我们建议白天为1.5-2.0,夜晚为0.4-1.0。Indirect Multiplier值,白天为0.6-1.0,夜晚为0.3-0.7。白天获得的直接光照比晚上的要强,这样白天会产生更好的间接光亮度。

我们看一看烘焙的效果。如上图所示,在白天的设置下,Intensity是1.8,Indirect Multiplier是1,Atmosphere Thickness是1,Exposure是3,这样我们获得了白天光照很好的房间。

如果设置正确,它应该会出现很好的GI效果,而且不会之前认为,在Unity光照中,有些暗部和间接光不是很好,缺乏全局照明的层次感。

上图就是夜晚的设置效果。在设置中,Intensity是0.4,Indirect Multiplier是0.25,Atmosphere Thickness是1,Exposure是0.1,基本上设置的数值都会往下降。特别是降低曝光度后,我们会得到月光的效果,但是它也有间接照明。

上图是人造光源的效果。Unity提供的除了常用的Point Light、Spot Light,还有一个就是Emissive自照明。Unity支持物体的像素照明,可以将物体的Emissve HDR值提高,提高以后就形成一个光源。

像灯管基本上就是一个Emissve照明的效果,它对房间进行了增强和补亮。为了体现夜晚效果的叠加,上图设置没有调得特别强,如果你希望更亮一些,可以在上面增加Area Light,进行补光。

如下图所示,我们可以看到Area Light关掉和开启的效果对比。

Area Light主要用途是什么呢?

如果大家比较观察细节,可以发现窗户的采光,除了太阳光照,有可能窗户外面世界亮的东西,都会发射光线进入房间。但是在计算机不会这样计算。因此,我们需要在窗户边上做一个同样大小的Area Light,往房间里面补光。

在补光之后,你会看到,尤其是在光照贴图的一侧,Area Light关掉和开启会有明显的视觉效果差异。这是因为右侧的区域没有Area Light,它不是非常仿真物理效果,如果加了Area Light,它会很仿真物理。

光照贴图的一个问题是,它们做的都是间接光,间接光一定不能将光照贴图曝掉,或者曝光度严重不足。所以我们需要一个间接光的空间去存储这些间接光信息。

如上图所示,如果间接光非常的亮,会导致我们看到的最右侧的图像效果。曝光那么多的时候,间接光贴图就损失掉了。

我们建议把Light Intensity设为1.8,HDR Exposure为16,或者Intensity等于3,HDR Exposure为16的曝光度效果。这样既能保证场景的亮度,又能让整体光照没什么问题。

了解一些Unity光照概念后,我们应该如何烘培呢?

如果你设置了很多烘培,但基于性能考虑可能不需要那么多物体需要烘培,不优化会导致场景中很多不需要烘培的物体烘培了光照贴图。

烘培完成后,光照贴图可能会非常大,特别对于一些移动游戏,没办法使用那么多贴图,所以正确的烘培也是非常重要的。

首先说一下Unity的Enlighten系统,它的一个优点是支持实时光GI。在构建过程中,构建光照条件后,我们可以调节光照的强度和方向,还可以移动光源。

但是它不能移动物体。如果静态模型要移动,Enlighten实时GI是不支持的,因为它需要构建光照环境,这就限制了Enlighten不是一个纯实时的GI,它是半实时的。

如果Enlighten使用不好,烘培速度会非常慢,我们通常会发现烘培卡在一个地方不动,慢到都想把电脑砸了,这种情况非常常见。所以大家必须按照Enlighten正确的方法去烘培才会比较快。

Enlighten好处是噪点控制非常好,如上图所示,画面的边缘没有太多的噪点,因为Enlighten的计算方式是不太会出现噪点的,它不是光线追踪算法,也不依赖于光子弹射。

Unity 5开始集成Enlighten,但Unity 2020 LTS版将是在内置渲染器包含Enlighten系统的最后一个版本,Unity 2021.1将完全移除Enlighten。

Progressive烘焙基于光线追踪,发射的一个光子弹射了多少次,弹射时分裂多少光子,再进行弹射。

Progressive的优点是:真实、GPU烘焙、烘培速度快。在同等的模型数量下,Progressive的计算速度比Enlighten快很多。Progressive的缺点是噪点控制比较差,当光子发射量不够时,它无法充满整个场景,因此无法计算出正确的光照。

如上图所示,我们来看看Progressive和Enlighten的烘培的差异。

Progressive和Enlighten的烘培时间基本上是相等的。Progressive会有一些斑点,Enlighten几乎没有斑点。但Enlighten的问题的缺乏细节,效果过于程序化。如果这是一个深邃的洞穴,过渡到最后面画面会变成黑色,几乎没有了。

如上图所示,这是我们提高Progressive的计算光子时烘培效果对比。Progressive会更加立体,更真实一些,Enlighten比较轻一些,或者说立体感不是那么足。

如上图所示,这是Progressive和Enlighten烘培后整体的预览效果,差异还是比较明显的。

如上图所示,这是一些烘培参数,当Direct Samples=40和Indirect Samples=400,对比Direct Samples=100和Indirect Samples=800,我们可以看到效果差异明显。

Direct Samples和Indirect Samples等同于直接光的采样数量和间接光的采样数量。如果采样越多,光子出现得越多,它就会将整个环境填得更加均匀,更加符合真实的世界。

真实世界的光子是无限的,在计算机模拟的时候是靠光子的数量来模拟的,所以我们尽可能在烘培的时候要把光子数量提高,这样会得到较好的效果。

使用Progressive时最大的问题是:在室内的情况下,要尽可能把整个烘培的精度提高,因为室内低频光比较多,间接光受到的影响比较多,室外可以稍微降低该值,提高烘焙效率。

现在谈谈Unity的光照方案。

移动游戏方面,建议大家使用混合光照技术,效率更高和更为逼真。近景可以使用动态阴影,远景使用Shadow Mask,这样可以降低Shadow Pass的压力。

例如:5-20米是使用动态阴影,远景全部使用Shadow Mask,这样手机平台上既可以获得动态阴影,又可以获得高的性能,不至于手机玩一会儿就会很烫的情况发生。

我们看一看混合光照的拆分情况。

如上图所示,Baked Lightmap和Shadow Mask在烘培后,一个是RGB通道的图,另一个是单通道。如果大家有能力修改,我们可以将单通道的图变成四通道来进行变化。

我们烘焙一个Lightmap的时候,Shadow Mask可以烘培四个时间段,例如:8点、11点、15点、17点。烘培完成后,我就可以通过Lit的方式把它Lit成变化,使它有间接光照。

Lightmap只使用一套,但我们可以对它进行扩展。Shadow Mask根据昼夜变化的时间,做成四套带有间接光照的,这样便可以根据项目进行深度的改进。