Unity 5.6中的混合光照(下)

时间:2021-04-01 07:07:36

https://mp.weixin.qq.com/s/DNQFsWpZm-ybIlF3DTAk2A

《Unity
5.6中的混合光照(上)》
中,我们介绍了混合模式,以及Subtractive模式是如何工作的。如果还不熟悉混合光照,请先去了解它背后的原理。

对Shadowmask的支持是新混合光照模式中的一个重要新功能。此外,还有密度与方向性贴图,Unity现在能为所有的光照类型生成Shadowmask了。与Subtractive模式不同,Shadowmask可以将所有光照类型的实时与烘焙阴影无缝混合。这意味着我们可以获得远距离阴影。出于性能考虑,可以在近处使用实时阴影而远处使用烘焙阴影,从而保持更低的Draw
Call数量。与Subtractive模式相反,Shadowmask功能还可以生成高质量的实时镜面高光。除了这些功能外,还对UI做了改进与重构,添加了新的调试模式,以协助你更好的在场景中设置光照。

这个视频展示了使用中的Shadowmask 和Distance Shadowmask。预计算实时GI在这个场景设置中已完全禁用。

现在,我们已说过Subtractive模式就是Unity中旧有的Mixed模式。但除那之外,Lighting Mode菜单中还有两个新的选项: Baked Indirect 和Shadowmask。要重点注意的是,Baked Indirect和Shadowmask不是质量设置。所有模式都有自己独特的功能特性,它们能在不同的使用场景中发挥不同的作用。

Shadowmask的主要功能本质上非常容易理解,它可以解决Subtractive无法完成的事情。Shadowmask不仅能处理方向光,还可以使用点光源和聚光灯混合实时与烘焙阴影,无需增加双重阴影/光照,即可正确合成重叠的阴影。在继续之前,我们需要先定义阴影距离的概念,它与光照模式紧密相关。许多新手用户不知道这个概念,但要正确高效地创作场景,必须要掌握这个知识。否则,很容易就会面对不必要的draw
call和帧率的下降。

阴影距离和阴影投射物的概念

在Unity中,阴影的行为由阴影距离和光照模式决定。查看阴影距离的一种快速方式就是使用Shadow Cascades模式。在场景视图中可以选择Shadow Cascades模式来显示阴影距离。这个参数可以在Quality设置中修改。更改阴影距离的另一个方式是通过API调用,但相关的使用案例相当有限。不过,它在某些极端情况下有些作用(例如,当需要在某些光照模式中为了降低draw
call而减少阴影距离)。

Unity 5.6中的混合光照(下)

因此,几何体在阴影距离之内还是之外,会影响阴影的行为,并对性能产生直接影响。

实际上,如果打开Quality设置(Edit > Project Settings > Quality),会发现有很多参数可用来调整阴影的设置。很可惜,这是UI中的隐藏部分,大部分用户都不知道它的存在,除非在需要时搜索到这些参数。

Unity 5.6中的混合光照(下)

尤其是可以在Distance Shadowmask和Shadowmask之间切换的Shadowmask功能选项。默认选中的是Distance Shadowmask选项,下文会讨论这两个模式之间的区别。让我们先从Shadowmask开始。

Shadowmask

在Shadowmask模式中,静态对象通过Shadowmask从其他静态对象接收阴影,不必考虑阴影距离。来自动态对象的阴影仅能通过阴影距离内的阴影贴图获得。动态对象通过阴影距离内的阴影贴图接受来自其他动态对象的阴影。来自静态对象的阴影仅能通过光照探针获得。

现在,当你同时在动态对象和光照贴图静态对象上使用Shadowmask模式时,你首先可能会发现问题就是,动态对象的阴影(阴影贴图)和来自光照贴图静态对象的烘焙阴影之间的不一致。当前(针对5.6),Unity在运行时仅支持简易版本的PCF( Percentage Closer Filtering )阴影,这种阴影很简陋,走近时还可能会出现阴影瑕疵。因此,动态对象是不可能获得软阴影的。与之相比,静态对象则相对较容易获得软阴影。实际上,通常需要增加分辨率以渲染更多静态对象的阴影,因为你需要更多的纹理像素来定义一张光照贴图上的阴影。只有这样,你才能渲染出与来自动态对象的阴影贴图相近的阴影。

Unity 5.6中的混合光照(下)

你可以看到,使用高分辨率光照贴图,来自静态对象的烘焙阴影与来自动态对象的阴影贴图已十分接近。

Unity 5.6中的混合光照(下)

使用低分辨率的光照贴图,来自静态对象的烘焙阴影与来自动态对象的阴影贴图明显不同。

关于Shadowmask模式的一个友情提示:动态对象仅会在阴影距离内投射阴影贴图。而静态对象,无论阴影距离是多少,仅会投射烘焙阴影。Shadowmask 和Distance Shadowmask两者均可提供实时镜面高光。

那么进一步的问题来了,什么是Distance Shadowmask?它与Shadowmask有何不同?

Distance Shadowmask

普通的Shadowmask模式要比Distance Shadowmask模式产生更少的Draw Call。为什么呢?

这是因为Distance Shadowmask的行为是由阴影距离决定的。在阴影距离内,动、静态对象都会渲染进阴影贴图,静态对象可以在动态对象上投射锐阴影。超出阴影距离,静态对象会通过预计算Shadowmask接收来自其他静态对象的高质量阴影,而动态对象则通过光照探针与LPPV,接收来自静态对象的低分辨率阴影。

这样应该能解释清楚Distance Shadowmask模式下动、静态对象的阴影投射方式以及为何Shadowmask模式要比Distance Shadowmask模式资源消耗更少了。基本上,阴影贴图的性能消耗要高于烘焙阴影(因为它们在每帧都进行渲染,而烘焙阴影是保存在一个纹理/光照贴图中的)。

在Shadowmask模式下,动态对象仅会在阴影距离内投射阴影贴图。Distance Shadowmask的性能消耗更大,因为静态对象也可以在阴影距离内投射实时阴影贴图,从而使Draw Call增加。这也就是为什么Distance
Shadowmask模式更适合高端PC或游戏主机。而Shadowmask则作为一种更廉价的解决方案,推荐在中低端设备使用。

Shadowmask中的遮蔽

有关Shadowmask的功能,我还想就不同对象类型遮蔽的工作原理进行详细说明。在上一篇文章中,我们谈及了为何光照探针的放置位置对于动态对象接收来自静态对象的阴影如此重要。本质上,动态对象需要光照探针从遮蔽物采样遮蔽数据。因此,Subtractive模式中的探针遮蔽概念同样可以直接适用于Shadowmask和Distance
Shadowmask。

有关对象是如何根据其类型与光照模式接收对应阴影的快速参考可以查看下面的光照模式参考卡片(Lighting Modes Reference Card),甚至可以打印出来以备不时之需。

Unity 5.6中的混合光照(下)Unity 5.6中的混合光照(下)Unity 5.6中的混合光照(下)

作为Quality设置的Shadowmask

在Unity 2017.1中,Shadowmask和Distance Shadowmask选项被移到了Quality设置中,这么做的原因有两点。

首先,我们希望用户能对阴影行为能有更多艺术性的控制,所以可以在运行时对模式进行切换。例如,你可以在同一场景中的室内环境使用Shadowmask(比如在机库中实现软阴影),在室外环境时切换到Distance Shadowmask。事实上,我们在《Unity
2017中的混合光照》
中已经提及了如何用API来实现这个操作。

其次,可以针对不同的硬件配置设置不同的要求。例如,在一个游戏中,可以在菜单UI上显示一个用户可以调整的设置选项,或者如果你要发布游戏到Steam,可以在低端硬件上使用普通的Shadowmask,在高端PC上使用Distance Shadowmask。

我们之所以能这样随心所欲进行设置,正是因为技术上在Shadowmask 和Distance Shadowmask之间的切换非常简单,唯一的缺点就是Draw Call的数量,但不管怎么说,最后都是取决于用户。

技术限制和调试工具

最后,让我们聊聊Shadowmask功能(Shadowmask 和Distance Shadowmask)的技术限制,以及能帮你在设置过程中进行问题诊断的调试工具。

现在,你已知道如何及为何使用Shadowmask,让我们来聊聊它的限制。由于技术约束,在一个场景中,Unity仅支持4个重叠的混合灯光。如果在相同位置有超过4个的混合灯光,其中之一就会降级为烘焙。通常如果你看到其中有某个灯光突然爆亮,你马上就能发现问题。

好消息是,我们有个可视化调试工具可以帮你解决该问题。如果将场景的visualization模式从“Shaded”切换到“Light Overlap”,你可以看到问题区域显示为红色高亮。

Unity 5.6中的混合光照(下)

值得一提的是,与点光源或聚光灯不同的是,方向光没有定义的边界,它是全方向的。因此,你在调试重叠的混合灯光时,总要将其考虑在内。在屏幕上,你可能只看到4个重叠灯光,但实际上,方向光可能已在某些位置与之有了交叉。如果在场景中使用了多个方向光来进行照明(例如作为补光),那情况就有点麻烦了,所以好好使用它。

Baked Indirect

目前为止我们已经介绍了Subtractive模式、Distance Shadowmask和Shadowmask功能。还剩一个模式,Baked Indirect。

与Shadowmask复杂的选项相比,Baked Indirect模式相当容易理解。Baked Indirect没有使用任何Shadowmask。所以在这个模式中没有远距离阴影。在阴影距离之内,所有静态和动态的对象都投射 实时阴影贴图。但超出阴影距离后,就没有阴影。

在Baked Indirect中,除了间接照明之外所有的东西都是实时的。这意味着,实时光照、实时阴影以及实时镜面高光,但是反弹的光照信息储存在光照贴图中,是静态的。在这个模式中,你能做的事情有限,但是你可以开动脑筋做些创造性的事情。下面你会看到摇摆的Baked Indirect模式混合聚光灯,是如何伪造实时全局照明的。

你可以看到灯光在变化,亮度忽明忽暗。但是,如果你仔细观察街灯的间接照明,你会发现它并没有变化。所以从技术上来说,你可以移动你的灯光,但不能太多,否则会出现阴影瑕疵。在下面的视频中,你会看到在场景中移动对象时,间接照明是如何导致这种类型阴影瑕疵的:

关于Unity 5.6中的混合光照就介绍到这里,我们还会继续为大家分享Unity相关的技术文章在Unity官方中文社区(unitychina.cn),请保持关注!