Origin
zhuanlan.zhihu.com
Tags
Unity
烘焙光照
流程规范
技术详解
项目
收藏夹
创建时间
收藏类型
Cubox 深度链接
更新时间
原链接
描述
现在是北京时间晚上 11 点半,起来搞点小文章 778。
很久没有混迹知乎了,今天突然起了兴致,决定放一篇远古时期写的文章,分享给大家。
文章知识点是我当时对 Unity GI 的认识,技术大佬们看到有纰漏的地方就凑合着看吧哈哈,不过这些内容对美术来说,还是是一定帮助的。
参数篇
写在前面
什么是全局光照? 全局照明(GI)是一个系统,用于模拟光从表面反射到其他表面(间接光)的方式,而不是仅限于直接从光源(直接光)照射到表面的光。 全局光照 = 直接光照 + 间接光照 那什么是直接光照?什么是间接光照?
在 Unity4 中,我们可以试试打一盏灯照亮物体,会发现物体在光源没有覆盖的地方,是一片死黑的。这就是仅考虑直接光照的结果。现实世界中,光线到达物体表面后被弹射开去,在空气中传播,在各个表面来回弹射,直到能量消耗殆尽。可以想象一束光投进窗户,从而整个房间的阴暗角落也被照亮的画面。这就是间接光照效果。然而,实现间接光照的算法非常复杂,计算速度太慢,用过 3D Max 渲染的同学应该知道渲染一张图片需要多长时间。所以,面对游戏等实时渲染领域,一秒钟需要渲染数十张图片以达到流畅的画面感的要求,要实现全局光照(GI)效果,显然需要另寻蹊径。
在游戏领域,解决这一局限性的一种方式就是:只为预先知道不会移动的物体(即被标记为静态的物体)计算间接光照。这样慢的计算可以提前完成,同时由于对象不移动,所以以这种方式预先计算的全局光照在运行时仍然是正确的。 Unity 支持这种称为
Baked GI
(也称为Baked Lightmaps
)的技术,也就是我们常说的 “烘焙”。除了间接光照外,Baked GI
还利用了更多的计算时间,可以从area light
和间接光中生成更逼真的柔和阴影。至此,Unity4 烘焙出来的 lightmap 信息包括了直接光 + 间接光 + 烘焙阴影。ps: 全局照明效果对于动态物体也是有办法的。Unity 提供了一套Light Probe的技术,可以将光照信息保存在这些预先布置好的灯光探头中,动态物体从这些探头中获得光照信息。当然,效果不会很精细。这种技术后面再做论述。
然而随着对游戏画面要求的日益提升,这种方法暴露了诸多局限性与不足。为此,Unity5 提供了一套更为完善的光照技术解决方案。有如下特点: - 支持预计算的实时全局光照效果
(Precomputed Realtime Global Illumination)
。 - 更完善的混合光照模式。 - 加入环境反射探针(refletion probe)
,以适配 PBR 效果。EnLighten 全局光照系统
Enlighten 为我们提供了预计算的实时全局光照
(Precomputed Realtime Global Illumination)
和混合光照(Mixed Lighting)
,这些技术不一定都用得上。根据项目要求和画面特点,选择性能和效果最平衡的技术方案,才是我们学习这套系统的关键。组成部分
一般来说,Unity 中实现照明的方法可以被分为 “实时” 和 “预计算 (烘焙)” 两种,都可以结合使用来创造逼真的场景照明。因此,我们需要了解全局照明的各个组成部分,以便根据相对优势和性能特征来选择适当的方法。
全局照明(global illumination) = 直接光照(direct lighting) + 间接光照(indirect lighting) + 环境光(ambient light)
直接光照 (direct lighting):
directional/point/spot
等光源的直接光照
- 环境光
(ambient light)
:对于动态物体,提供实时的环境光计算。实际上是 light probe。
间接光照 (indirect lighting):
directional/point/spot
等光源的间接光照(indirect bounce)
- 环境光
(ambient light)
:对于静态物体,作为简介光照烘焙到 Lightmap 中。
- 自发光材质
(emission Material)
Unity 对于 indirect lighting 的定义为:自光源发射,至少击中场景表面两次,最终到达摄像机的光线。
常用光源类型
常用的光源类型包括平行光
(directional light)
、点光源(point light)
、聚光灯(spot light)
、区域光(area light)
,这些光源可以为场景物体提供直接光和间接光效果,需要注意的是由于area light
计算过于复杂,目前只支持烘焙的实现方法。 下面以spot light
为例,通过构建一个纯净的实验环境,分别展示直接光照、间接光照的效果。ps: 暂时不用管间接照明是用哪种方法实现的。环境光
环境光表示场景周围的光线,并不是来自任何特定的源物体。它对整个场景的色彩基调起到重要作用。
可以在
Lighting面板
的Environment Lighting选项
中对环境光进行设置,它的色彩来源Source
可以设置成 - Skybox 与指定颜色的混合(Skybox)
- 指定固态颜色(Color)
- 渐变色(Gradient)
Ambient Mode
通常为自动设置,这取决于你当前使用的是Baked GI
还是Precomputed Realtime GI
。除非你两者都开了或者不开。PS:在 Unity 中,ambient light对于动态物体或未经烘焙的物体而言,是作为直接光照并实时参与计算的。对于静态物体而言,ambient light所有成分都被视为间接光照并参与到烘焙中。
下面展示
ambient light
作为直接光照与间接光照的区别。图一中环境光作为直接光参与实时计算,导致所有物体都是同一种颜色。这是因为环境照明本身就作为从四面八方照亮物体的照明,没有考虑到物体与物体之间的遮挡关系。我们把这个问题叫做
环境光遮蔽(Ambient Occlusion)
问题,也就是我们常说的AO
。图二中,环境光作为间接光照,在烘焙过程考虑到光线从物体各表面弹射
(bounce)
,从而能够烘焙出柔和的阴影。如果要更明显的环境遮挡效果,Unity 还提供了烘焙 AO 到 lightmap 的功能,可在Lightmapping Settings
选项中勾选Ambient Occlusion
开启。自发光材质
与
area light
一样,自发光材质(emissive materials)
在其表面发射光线,可以在场景中作为光源照亮其他物体,但这毫无疑问,计算过程复杂,需要烘焙 (baked) 或预计算 (precomputed) 才能发挥效果,而这就要求自发光物体和被照亮的物体都必须是静态物体,而且需要 Shader 本身支持 Emission 效果。Emitted Light
自发光线也包含直接光和间接光部分。其直接光部分可视为对发光体自身进行照明,间接光部分对其他物体进行照明。以下摘自官方文档,对于全局光线的图解。
选择一种合适的光照技术方案
当你看到这里,相必你已经对全局照明效果的组成部分、光源的类型有了大致的认识,这有助于我们去选择一个合适的光照技术方案。 所以接下来,我们要学习的是对光照效果的控制,以及选择其合适的实现方式。 在本节中,我们将简要介绍不同方案的适用场合,相对优势和性能特征。
光照模式(Lighting Modes)
选中灯光,在
Inspector
面板中,你可以指定光源的光照模式,这个光照模式定义了该光源的预期用途。实时直接光照(Realtime)
实时直接光照的环境设置:把
Realtime GlobalIllumination
和Baked Global Illumination
勾选去掉,同时将Auto Generate
关闭并清空烘焙数据Clear Baked Data
。此时,realtime 灯光为场景提供实时直接光照,并能选择是否开启
实时阴影
。实时光照是在场景内对物体进行照明的最基本的方式,对于照亮人物或其他可移动的物体非常有用。但值得注意的是,在没有被光源范围覆盖的地方,这些区域是完全黑色的,因为没有反弹的光线
(bounced light)
。该问题见 上文阐述。因此,为了营造更逼真的场景,我们需要启用全局照明技术,Unity5 为我们提供了两套解决方案:混合光照(Mixed lighting)
和预计算全局实时光照(Precomputed realtime global illumination)
混合光照(Mixed lighting)
Unity 在 5.5 版本中加入了混合光照技术,是可以将 Realtime 光照与
Baked GI
混合的一种技术方案,让我们可以按照实际需求和主观意愿,去组合搭配。典型应用一:灯光的间接光部分被烘焙到 lightmap 中,烘焙完成后,该光源还能继续参与实时光照计算,以提供材质的法线高光效果。 典型应用二:将灯光对静态物体产生的阴影烘焙到单独的 lightmap 中,这种 lightmap 叫做ShadowMask,在运行时,根据ShadowMask,对动态物体产生的实时阴影能够与烘焙阴影更好地混合。
烘焙 GI(Baked GI)
开启方法:只要勾选
Baked Global Illumination
,就会启用Mixed Lighting
的技术方案,因为Baked GI
是它的一部分。我们只需要将所有光源设置成Baked
模式,确保只使用了Baked GI
技术。 Unity 在运行时之前预计算这些灯光,并且不会在任何运行时内计算它们。这意味着Baked
灯没有运行时间的开销。 Unity 将 Baked
灯光的直接和间接照明映射到光照贴图(lightmap)
照亮静态游戏对象)和光源探测器(light probe)
(照亮动态光照游戏对象)。 Baked
模式也是唯一的不能在其他动态 GameObjects 上投射阴影的 light 模式。Baked GI 的优点
- 来自静态 GameObjects 的高品质阴影,而无需额外成本。
- 提供间接照明。
- 静态 GameObjects 的所有光照来自 Shader 中的一张 Texture,即
Lightmap
。
Baked GI 的缺点
- 没有实时直接照明(导致也没有镜面高光
(Specular Highlight)
效果)。
- 动态 GameObjects 要获得来自静态 GameObjects 投射的阴影,只能使用
Light Probes
,但是其效果是低分辨率的。
- 与实时照明相比,Lightmap 图集会导致内存需求增加,因为光照贴图包含直接照明信息而需要更加精细。
混合光照模式(Mixed Lighting Mode)
Mixed灯光
是指将Mode
属性设置为Mixed
的 Light 组件。 Mixed灯光
可以在在运行时可以改变其 Transfrom 属性和灯光属性(如颜色或强度),但只能在有限的范围内。 它们照亮静态和动态 GameObjects,总是提供直接照明,并可以选择提供间接照明。 混合光照下的动态 GameObjects 可以在其他动态 GameObjects 上投射实时阴影。场景中的所有混合灯光使用相同的混合光照模式
(Mixed Lighting Mode)
,需要在Lighting
面板Mixed Lighting选项
的Lighting Mode
中进行选择,有 Subtractive、Baked Indirect、ShadowMask、DistanceShadowMask 四种模式。Subtractive 模式
在
Subtractive模式
下:- 会将
Mixed
灯光的直接照明、间接照明、阴影信息全部烘焙到 Lightmap 中去,这一点跟Baked GI
是一样。
Subtractive模式
也是四种混合光照模式中,唯一会将直接照明烘焙到 lightmap 的模式。
- 在烘焙完成后,
Mixed
仍然可以给动态 GameObjects 提供实时光照,并支持高光效果。但是,他们只能通过Light Probes
从静态 GameObjects 接收阴影。
- 在减法模式中,主方向光是唯一能够将动态 GameObject 中的实时阴影投射到静态 GameObjects 上的光源。但该模式不能保证烘焙阴影和实时阴影的正确组合。因此,
Subtractive模式
提供Realtime Shadow Color
设置。
Unity 在 Shader 中使用此颜色将实时阴影与烘焙阴影进行合成。要做到这一点,它可以减少动态 GameObjects 覆盖区域的光照效果。因为引擎无法提供一个预定的正确值,所以选择一个适用于任何给定场景的值是自己的艺术选择。
注意:Mixed Light的Shadow Type设置若为No Shadow,该光源只有间接光部分参与烘焙,并可以为所有物体提供实时光照。这与文档描述的不符,疑似 Unity 的一个 Bug,是一个要注意的问题。所以,要么所有 Mixed Light 都开启阴影选项,要么就都设置成 Baked 模式,只留一个平行光作为 Mixed 模式,并注意开启阴影选项。
仍然存在的不足: - 它不能为静态物体提供实时直接照明,因此不提供高光效果。 - 它不提供将动态 GameObject 中的实时阴影投射到静态 GameObjects 上,除了一个方向灯(主灯)。 - 它无法很好地解决动态和静态阴影组合。
Baked Indirect 模式
对于设置为 Baked Indirect 模式的灯光,生成的 Lightmap 和 light probe 只包含间接光部分信息,并且不执行阴影的烘焙。烘焙后,Mixed 灯光会继续为所有物体提供实时直接照明和实时阴影。 Baked Indirect 模式的性能要求使其成为中档 PC 和高端移动设备的理想选择。
优点:
- 它提供了与实时照明相同的视觉效果。
- 它为静态和动态 GameObjects 的所有组合提供实时阴影。
- 它提供间接照明。
缺点:
- 与其他混合光模式相比,它具有更高的性能要求。
- 由于 Unity 实时阴影会有距离限制,远处的阴影将不会被渲染。
ShadowMask 模式
ShadowMask
是一张遮罩图,它与相应的光照贴图共享相同的 UV 布局和分辨率。它的每个像素储存最多 4 个灯光的遮挡信息,因为纹理最多只有 RGBA 四个通道。Unity 会烘焙静态 GameObjects 间的阴影信息,并将它们存储在一个单独的 Shadowmask Texture 中,同一个像素最多可保存 4 个灯光的遮挡信息,如果超过 4 个灯重叠,任何额外的灯产生的阴影将会被烘焙到 lightmap 中去。光探头也可以接收最多 4 个灯的相同信息。
在
ShadowMask模式
下:- 静态 GameObjects 通过
ShadowMask
接收来自其他静态 GameObjects 的阴影。他们也会从动态 GameObjects 中获得实时阴影,但是只有阴影距离(Shadow Distance)
内的阴影。可在QualitySettings面板
中设置。
- 动态 GameObjects 通过
ShadowMap
从阴影距离内的其他动态 GameObjects 接收阴影。他们还通过 Light Probes 从静态 GameObjects 获得阴影。阴影保真度取决于场景中Light Probe
的密度,以及在Mesh Renderer
上选择的Light Probes模式
。
PS:ShadowMap叫做阴影贴图,Unity 是实现实时阴影过程中生成的一张贴图。注意与 ShadowMask 做区分。
Unity 会根据
ShadowMask
(包含静态 GameObject 阴影信息)和ShadowMap
(包含动态 GameObject 阴影信息),在 Shader 中做相应的处理,将静态和动态 GameObjects 的重叠阴影组合在一起,优点:
- 为所有物体提供与实时照明相同的视觉效果,因此具有法线高光效果。
- 所有
Mixed光源
都能提供从动态 GameObjects 到静态 GameObjects 的实时阴影。
- 很好的融合了动态和静态阴影。
- 适用于中低以上的性能要求,因为静态 GameObjects 的阴影不是实时计算的。
- 提供间接照明。
缺点:
- 它只能通过 Light Probes 将静态 GameObjects 中的低分辨率阴影提供给动态 GameObjects。
ShadowMask
允许最多 4 个重叠的光线量。
ShadowMask
贴图增加了较多的纹理内存。
DistanceShadowMask 模式
DistanceShadowMask模式
是ShadowMask模式
的升级版。在阴影距离
(Shadow Distance)
内的 GameObjecs(Edit > Project Settings > Quality > Shadows): Unity 会将动态和静态的 GameObjects 渲染到ShadowMap
中,换而言之,就是都进行实时阴影计算。由于这个原因,DistanceShadowMask模式
比ShadowMask模式
具有更高的性能要求。在
Shadow Distance
之外的 GameObjecs:- 静态 GameObjects 通过
ShadowMask
从其他静态 GameObjects 接收高分辨率阴影。
- 动态 GameObjects 通过 Light Probes 接收来自静态 GameObjects 的低分辨率阴影
实时全局光照(Realtime GI)
尽管 Mixed Lighting 已经很完善,但还是无法对场景的间接照明做动态变化。为此,Unity 5.0 新增了号称为 “预计算实时 GI
(Precomputed realtime GI)
” 的新技术,通过这种方法,可以创建具有丰富全局照明的光照环境,并实时响应照明变化。 一个很好的例子就是昼夜变化系统:光源的位置和颜色随时间而变化。 用传统的Baked GI
,这是不可能的实现的。需要注意:Realtime GI仍然需要一个类似于上面提到的烘焙(baked)的预计算(precomputed)阶段,仍然限于静态对象。但是,它不仅在构建时预计算光线的反弹,而且还会预先计算所有静态物体间光线反射可能经过的路径,并对这些信息进行编码以供在运行时使用。所以对于所有的静态对象来说,预计算(precomputed)阶段解决的问题是 “如果任何光照射到这个表面,它会在哪里弹跳?” 然后 Unity 会保存这个信息,指出光线可以传播哪些路径以备后用。最后的照明是在运行时通过将现有的实际灯光输入到先前计算的光传播路径中完成的。更多内容见技术细节。
这意味着灯的数量和类型,其位置,方向和其他属性都可以改变,间接照明也会相应更新。类似的,也可以改变物体的材质属性,例如它们的颜色,它们吸收多少光线或者它们自己发射多少光线。
虽然预先计算的实时 GI 也会产生柔和阴影,但是除非场景非常小,否则它们通常必须比
Baked GI
所能达到效果的更粗糙。还要注意的是,虽然预计算实时 GI 在运行时计算最终的照明,但它在几个帧内迭代地计算的,所以如果在照明中做了大幅度的改变,则需要更多的帧才能完全生效。尽管这对于实时应用来说足够快,但是如果目标平台资源非常有限,那么使用Baked GI
可能会更好地实现更好的运行时性能。使用 Realtime GI
实时照明与
Realtime GI
的组合是 Unity 中最灵活和最现实的照明选项。要启用Realtime GI
,打开Lighting窗口
并勾选实时Realtime Global Illumination
。启用实时 GI 后,实时灯会向场景中提供间接照明以及直接照明。但这种组合适用于光源变化缓慢,对场景有高度的视觉冲击的情况,如太阳在天空中移动,或者在封闭的走廊中缓慢的脉动光。不要使用 Realtime GI 来快速改变灯光,因为迭代的计算造成的延迟效果得不偿失。
请注意,与较不复杂的
Baked GI
相比,实时 GI 使用大量的系统资源。全局照明在 Unity 中由一个名为 Enlighten 的中间件管理,该中间件具有自己的开销(系统内存和 CPU 周期)。因此
Realtime GI
适用于针对中高端 PC 系统的游戏,以及针对 PS4 和 Xbox One 等平台的游戏。一些高端移动设备也可能足够强大,以利用此功能,但您应该保持场景小,实时灯光分辨率低以节省系统资源。要禁用某一光源的实时 GI 的效果,可以选中该光源 Gamobject,然后在 Light 组件中将
Indirect Multiplier
设置为 0。这意味着 Light 不会提供任何间接光源。要完全禁用实时 GI,请打开Lighting窗口
,并取消Realtime Global Illumination
。技术细节
预先计算的实时 GI 模式:Unity 仅预先计算表面到表面的信息:物体间光线可能会经过的路径。
在运行时,Enlighten 利用这些预计算的信息,通过 CPU 计算光线的弹射,因为过程计算量很大,所以它被分散到几个帧中计算,这就是上文一直说的迭代计算。并将最终的结果储存在动态光照贴图 (Dynamic lightmap) 和光照探针 (light probe)。换句话说,Realtime GI 最终的实现方式还是 lightmap,只不过这个 Lightmap 是在运行时动态更新的,而且它需要几帧时间,直到光线完全反射到场景中的静态元素上,动态光照贴图和光探针才能获得到最终结果。
对于属性缓慢变化的灯(例如发光的太阳在天空中移动),这不会造成问题。但是,对于属性变化很快的灯(如闪烁的灯泡),实时 GI 的迭代计算的特性可能不适用。而且快速的变化属性的照明不会显著地影响光系统,所以在计算中包含它们没有意义,可以考虑将这部分的光的 realtime GI 效果关掉,通过调节
light组件
上的Indirect Multiplier
为 0。有几种方法可以解决迭代计算造成的延迟问题。一种方法是减少实时光照分辨率 (在
Lighting面板
的Lightmapping Settings
选项中的Indirect Resolution
属性)。因为这会减少的计算量,照明迭代的速度更快。另一个选项是增加实时 GI 运行时的 CPU 使用率设置。通过投入更多的 CPU 时间,运行时更快地迭代。权衡当然是其他系统接受较少的 CPU 时间来完成他们的工作。这取决于项目的具体情况。缺点
- 由于动态光照贴图
(dynamic lightmap)
和光照探针(light probe)
采样,用于存储由 Enlighten 照明系统计算的实时间接反弹,增加了 Shader 计算复杂度和性能消耗。
- 间接照明是迭代计算的,更新需要一定的时间,所以光源的属性变化不能太快。 虽然一个适当的 HDR
ToneMapping
可能会帮您掩盖这一缺点。
GI 与材质
物体的材质属性也是影响光线的一个重要因素,材质表面的颜色,直接决定了从该表面弹射出去的光线的颜色。还有更多的影响因素如:PBR(基于物理的渲染) 材质的金属度
(Metallic)
和粗糙度(Roughness)
会影响光线的吸收和反射程度。GI 的局限性
无论是
Baked GI
和还是PreComputed Realtime GI
都有一个局限性,即烘焙 / 预计算中只能包含静态物体,所以移动的物体不能将光线反射到其他物体上,反之亦然。 不过,他们仍然可以使用Light Probes
拾取静态物体的反射光。将 Light Probe
事先布置在场景中的,在烘焙 / 预计算阶段, Light Probe
会储存其位置上的照明信息,然后在运行时阶段,动态物体会获取附近的light probe
里面的光照信息,从而近似地获得静态物体反射的光线。在 PBR 材质中有一个很重要的照明部分:IBL(基于图像的光照)。它基于环境贴图
(Environment Map)
的每个像素作为入射光,计算来自环境贴图各个方向的入射光对物体的光照信息,是 PBR 中模拟物体周围环境光照的一个重要方法。这也是 GI 算法无法达到的效果。对应相关的技术是反射探针(Refletion Probe)
以及Lighting面板
的相关设置。后记
以上便是 “理论篇” 的全部内容,一部分描述翻译自 Unity 官方文档。 接下来会在 “实践篇” 重点介绍如下内容: - 项参数详解 - 烘焙流程 - 常见问题及技巧 - PBR 效果等内容 >
参数篇
前面写了写给美术看的 Unity 全局光照技术 (理论篇),有兴趣的可以先看看,上篇文章末尾写了会有 “实践” 篇的内容,其实是骗你们的拉哈哈,其实当时我想写来着,不过后来鸽了,于是找了下库存还有哪些文章可以发,找到这篇 “参数” 篇,就分享出来吧。
Unity 到 2019,GI 系统相比已经有了很大改进,可能你会觉得文章已经过时。对于旧知识看法,本人认为还是有重要的学习价值的。如果你熟悉一种技术的发展历程,你会知道技术中的一些细节为什么要这样实现,这是有利于充分掌握这种技术的。
好了,不想多说废话了。
读完 “理论篇” 内容,希望你们能够理解 GI 的核心思想:
Light Bounced
光线弹射。光线从光源出发,击中物体表面随即反射进摄像机,我们把这一部分照明就做直接照明;若光线在各个表面弹射,最终到达摄像机的部分叫做间接照明。在基于物理渲染的思想中,还需要考虑表面材质对光线的反射率(Albedo)的影响。通俗地理解:即,要考虑光线能量有多少被吸收,导致被反射出去的光线呈现怎样的强度和颜色。表面的反射率(Albedo)一般用 RGB 表示。
实现 GI 有两种方案
Realtime GI
和Baked GI
,对应的最终实现的形式为Dynamic Lightmap
动态光照贴图和Lightmap
光照贴图。以下全文将主要围绕:控制Dynamic Lightmap
和Lightmap
的效果的参数展开。如果对上面的概念还不太清楚,建议先认真看一遍 “理论篇” 内容会更好。
我们对 GI 的概念有了一个大致的认识后,下面我们要学习的是:Unity 的 GI 程序到底做了哪些工作,以及我们要如何控制 GI 程序的。如果有不理解的地方,可以暂且跳过。在烘焙教程章节重点讲解。
GI Process
在 Unity 中,烘焙 / 预计算程序默认是自动处理
(Auto Generate)
的,也可以手动启动, 在这两种情况下,并不会影响编辑器的其他操作,因为这些过程在后台运行的。为了方便描述,以下全文把烘焙 / 预计算这个过程统一称作 GI 程序(GI Process)
。当 GI 程序正在运行时,编辑器右下方将出现一个蓝色的进度条。 根据是否启用了
Baked GI
或Precomputed Realtime GI
,需要完成不同的阶段。 关于当前进程的信息显示在进度条的顶部。在上面的例子中,我们可以看到我们处于 5/11 的进度中,即
Clustering
阶段,并且仍剩余 108 个 jobs 才能够进入下一个阶段 6 中。各个阶段如下所示:以上阶段从左到右,从上到下一步步执行。 需要注意的是:仅开启
Precomputed Realtime GI
的话,Baked GI
的所有阶段将不会执行。 如果仅开启Baked GI
的话,GI 程序会执行所有流程 (包括Precomputed Realtime GI
),这是因为Precomputed Realtime GI
阶段的处理并不只是为Realtime GI
设计,它构建了间接光照所需要的计算环境。**所以下文中,仅开启 Baked GI 的情况下,一些专属于 Realtime GI 的参数依然会生效,就是上述这个原因。
如果想要进一步了解 GI 程序各个阶段做了什么,产生了哪些数据,可查看可视化 GI 数据内容,会有部分相应的描述。
GI 参数设置
Lighting Window
(menu: Window > Lighting > Settings)是 Unity 全局照明(GI)功能的主要控制面板。通过Lighting窗口
,你可以调整 GI 进程中的各个方面,根据需要来自定义场景或优化质量,性能和存储空间。 这个窗口还包括环境光,雾效、光晕等设置。 Lighting窗口
有三个选项卡:Scene
、Global maps
、Object maps
。我们重点要看的是 Scene 窗口。Environment
环境照明部分包含天空盒
(Skybox)
,环境光(Environment Lighting)
和环境反射(Environment Refletions)
的设置。Skybox
Unity 中的 Skybox 有三个 Shader 可以选择:其中
Procedural
是 Unity 默认的 skybox,由程序控制,无法自定义效果,配合Sun Source
绑定一个平行光可以实现昼夜变化的天空效果。6 Sided
和Cubemap
是传统的 Skybox 做法,Sun Source 无效。Environment Lighting
该项控制 Ambient Light:为物体提供环境光漫反射光照。颜色来源可以是上面设定的 Skybox 材质球,可以使固定的颜色或渐变色。具体看 “概念篇” 内容介绍。Environment Reflections
该项控制主环境反射设置,本质上是一张所有物体都可以使用的Cubemap
。环境反射与 Ambient Light 的区别在于,它提供的是逼真的环境光镜面反射效果,是基于物理的渲染 (PBR) 中重要的照明效果。
Unity 提供Refletion Probe技术,用于捕捉周围场景的图像,并将其储存为立方体贴图Cubemap。所以Refletion Probe的内容载体是Cubemap。
反射源属性
Source
可以设定主环境反射的来源。如果 Source 为skybox
,需要烘焙 / 预计算后才有效果,过程中生成一个Refletion Probe
供所有对象使用,并捕捉当前 Skybox 图像,将其保存为一个Cubemap
。若是Custom
,需要手动指定一个Cubemap
,可以立即看到效果。反射强度
Intensity Multiplier
:控制主反射源的反射强度。Bounces
属性会影响场景中所有Refletion Probe
的烘焙效果。如果场景布置了多个交错重叠的Refletion Probe
,该属性决定了Refletion Probe
捕捉的图像中是否包含其他Refletion Probe
的反射。默认是 1,则 Unity 仅考虑初始反射(从反射源属性中指定的天空盒或立方体贴图)。场景 Lightmapping Settings
通过
Lightmapping Setting
面板,可以总体地控制场景的 GI 各项参数。Realtime GI
Indirect Resolution
间接光分辨率:物体单位表面积占 Dynamic Lightmap 的像素数量。 增加此值可提高间接光的视觉质量,但也增加了烘烤光照贴图所需的时间。此值对烘焙时间的影响最为严重, 想要快速预览效果可降低此值。默认是 2,一般建议户外大场景 0.5~1,室内场景 2~3。Directional Mode
:默认为 Directional,会额外烘焙一张 directional map,储存物体表面上每个点上的的主导入射光的信息。配合烘焙的 lightmap,起到加强凹凸感的作用。Realtime GI 和 Baked GI 都可开启,但实际作用并不大,实时光照带来的凹凸效果更明显。Indirect Intensity
:控制所有间接光强度的一个总控参数,数值介于 0 和 5 之间。大于 1 的值会增加间接光的强度,而小于 1 的值会降低间接光的强度。 默认值是 1。注意:对于 Mixed Lighting,烘焙后再调节该参数是无效的,因为间接光已经烘焙在 lightmap 上了。Albedo Boost
:调节此值可控制表面之间反射的光线量,增强场景中材质的反照率。此值越大,材质的Albedo
越趋向于白色。默认值 1 是物理上准确的。Albedo 描述了光线击中表面后会呈现一种怎样的状态,比如,在 PBR 材质中,完全光滑的金属会吸收所有光线,所以任何光线击中表面都不会被反射出去,也就不会有间接光照的效果。又比如,蓝色的光线击中 Albedo 为黄色的表面,发射出去的光线会呈绿色。
Baked GI
接下来了解 Baked GI 的参数:
lightmapper
: 使用此选项指定要使用哪个内部光照计算软件来计算场景中的光照贴图。 选项是 Enlighten 和 Progressive。 默认值是 Enlighten。Progressive 渐进式光照系统是用来快速预览效果的,但该功能仍处于试验阶段,可暂时忽略。Lightmap Resolution
:物体单位表面积占 lightmap 的像素数量。 增加此值可提高 Lightmap 的质量,但也增加了烘烤时间。 默认值是 40。此值最后还要跟每个物体上的 Scale In Lightmap 换算,才是能确定该物体最终占用的 lightmap 像素是多少。Lightmap Padding
:lightmap 上储存的是不同物体的光照信息,物体的像素块之间需要隔开一些像素,防止纹理采样时发成错误。这个 padding 就是物体隔开的像素数量。Lightmap Size
: 每张 lightmap 最大的尺寸值。如果Lightmap Resolution
越高,而Lightmap Size
的尺寸不足以 “装下” 这么多的像素,就最烘焙成好几张 Lightmap。在项目中,除了 lightmap 的大小需要控制外,还要尽量减少 lightmap 的数量,因为这会影响网格的合并。此值最大不能超过 2048。Compress Lightmaps
: 勾选了此选项,将会对烘焙好的 Lightmap 进行压缩,大大减少了图片内存大小,但质量也会降低,需要视实际情况而定,做最优的选择。一般建议是要勾选的,若效果不满意,可以考虑提高Lightmap Resolution
和Lightmap Size
。如果非得要去掉勾选,不进行压缩,建议得把Lightmap Resolution
和Lightmap Size
降低到合适的范围以减少内存大小。Ambient Occlusion
:当勾选时,开启表面间的环境光遮蔽效果。这仅适用于由 GI 系统计算的间接照明。 此设置是默认启用的。Final Gather
: 启用 Final Gather 时, 会提高 lightmap 的视觉质量,比如消除噪点等,但是会增加额外的烘焙时间为代价。具体原理我也没搞懂。。Lightmap Parameters
:除了Lighting窗口
的 GI 参数,Unity 还提供了一组常规参数来进一步地控制 GI 程序, 菜单中有做好的预设值可供选择,一般来说使用这些预设就足够了,默认是Default-Medium
。但您也可以新建一个Lightmap Parameters文件
来自定义你的设置。 有关更多详细信息见下文。物体 Lightmapping Settings
除了在
Lighting Window
面板全局地控制场景的 GI 参数外,有些参数还可以针对个别物体进行设置。 选中 GameObject 的 Mesh Renderer 组件,开启lightmap Static
,便会展开Lightmap Settings
栏,这里面的参数会结合Lighting Window
的场景 GI 参数,最终决定该物体以怎样的 GI 参数参与到 GI 程序中去。Scale In Lightmap
: 默认是 1,对应 Lighting Window 中的Lightmap Resolution
。假如Lightmap Resolution为 40,物体的Scale In Lightmap为 2,假设物体是 1x1x1 米的立方体 (6 个面),那么最终该物体占用的 lightmap 像素为:40x2x6 = 480 个像素。
Proprotize Illumination
:选中此框可指示 Unity 始终在光照计算中包含此对象。 用于强烈发射的物体,以确保其他物体将被该物体照亮。Lightmap Parameters
可以分配给 Lighting Windows 的场景设置,也可以应用于场景中的单个 GameObject 实例。Lightmap Parameters 用于存储控制 GI 功能的参数的一组值, 定义和保存 GI 的不同参数值,以便在不同情况下使用。 在创建时,它们存储在 Project 文件夹中,可以通过 Project 窗口进行访问。
通过创建 Lightmap Parameters,针对不同类型的 GameObjects,或针对不同平台和不同场景类型(例如,室内或室外场景)优化的预设,一般来说,使用 Unity 做好的几组预设便能应付大多数情况。
其参数过于复杂,不作解析,有兴趣可以去官网查看。
其它渲染相关的参数设置
Light Inspector
只介绍与烘焙有关的部分参数:
Mode
:用于指定该灯光以什么方式进行照明,有 Realtime、Mixed、Baked 三种。对应的要看 Lighting Window 开启的是哪种光照方案。Intensity
:灯光光照强度,Directional light 默认值为 0.5, Point, Spot or Area light 为 1。Indirect Multiplier
:间接光强度,不多解析。 应用:当处于阴暗环境(例如洞穴内部)需要更亮的间接光才能使细节可见时,这是非常有用的。 或者,如果要使用 “Realtime GI”,但要限制单个实时灯以使其仅发射直射光,可将 Indirect Multiplier 设置为 0。Cull Mask
: 可以有选择地排除不受灯光影响的对象。注意:该特性只适用于实时光照,烘焙过程是不会考虑该选项的。Shadow Type
: 设置这个灯光是否投射硬阴影(Hard Shadows)
,软阴影(Soft Shadows)
或根本没有阴影(No Shadows)
。该设置对于烘焙来效果同样适用。Hard Shadows
会产生边缘生硬的阴影。与Soft Shadows
相比,硬阴影并不特别真实,但是计算较为简单,使用条件限制相对较低。当灯光为
Baked
模式,Shadow Type
设置为软阴影时,将会烘焙出柔和的阴影到 Lightmap 中。 Baked/Mixed 灯光下的 Soft Shadows 有 Baked Shadow Radius 参数可以调整,该值越大,烘焙的阴影越柔。若灯光为
Realtime
,则是实时阴影计算,请注意,实时阴影的计算非常耗性能,开软阴影的代价会非常高,而且好需要看项目的质量控制设置(QualitySettings)
是否允许这样做,所以一般启用得是 Hard Shadows。Shadow
要对物体投射阴影,除了要 Light 的设置外,还需要对物体进行相应设置。 场景中的物体的 MeshRenderer 组件也具有
Cast Shadows
和Receive Shadows
属性,必须根据需要启用它们。主要注意的是,Unity 烘焙的阴影都是根据 “双面” 的方式生成的,所以上面所谓 “单面”“双面” 的情况只适用于实时阴影。 如果你发现烘焙前和烘焙后的阴影差别很大,检查是不是因为这个原因。
还有,烘焙并不能控制 mesh 是否接受投影,所有参与烘焙的物体会接受阴影。
技巧:
Shadows only
模式适用于:可以用一些物体来投射出想要的阴影效果,但并不需要渲染他们。需要强调的是,实时阴影模式下,他们都是 “单面” 投影的。Scene 窗口的可视化 GI 数据
Scene 窗口有许多绘图模式来帮助您可视化不同方面的场景内容。 其中包括一组模式,让你看到 GI 是如何影响你的场景。
默认的是 Shaded 模式,也就是正常渲染的效果,此外常用的还有 Overdraw,Mipmaps 等,但不在本文讨论范围,有兴趣可以自己试试。 与 GI 有关的模式是分为三类:
Global Illumination
:显示 GI 程序的一些必要数据以及 Dynamic Lightmap 的分辨率:Systems、Clustering、Lit Clustering Realtime GI
: 显示 Realtime GI 的数据以及 Dynamic Lightmap 的分辨率。 Baked GI
: 显示 Baked GI 的数据以及 Lightmap 的分辨率。最下方
Show Lightmap Resolution
复选框控制是否显示 lightmap 的分辨率,其作为棋盘格的形式与相应的数据混合显示。 比如你选择的是 Realtime GI 的 Indirect 模式,并勾选了此选项,就会显示 Indirect 数据以及 Dynamic Lightmap 的棋盘格。 通常来说,该选项是这里面最有用的功能,实时查看 lightmap 的分辨率,有利于我们对光照效果精度的把控。需要再次强调,Baked GI 会执行 GI 程序的所有流程,所以 Realtime GI 的数据也是可以看到,但反过来仅开启 Realtime GI,就看不到 Baked GI 的数据。 想要查看相应的可视化数据,需要确保 GI 程序已经完成了该步骤的计算。例如你要看可视化的 Clustering 数据,需要等待 GI Process 中 5/11 步骤执行完毕。具体见上文 GI Process。
当你关掉 Unity 重开,想要再看这些数据,需要重新执行 GI 程序,因为这些数据缓冲已经被清除。 你可以打开
Auto Generate
开关,并在 GI 程序执行过程中,切换到这些 GI 视图模式,可以看到他们是怎么生成的。下面来主要介绍几个常用的模式:
Shaded
System
GI 进程中 3/11
Create Systems
阶段,将根据物体的接近度和光照贴图参数自动将场景细分为多个 System,换句话说,System 即是共享相同的 Realtime Lightmap 的对象组。 这是为了在更新间接照明时,实现多线程和优化性能。 上图的可视化显示了不同颜色的 System。UV Charts
这显示了在 Realtime GI 进程的 4/11
Create Atlas
阶段时使用的优化的 UV 布局。 Enlighten 会自动生成物体的第三套 UV 用作生成Dynamic Lightmap
,UV Charts
表示其实就是 lightmap 中属于物体自身的一小块纹理区域,详细可见官方教程,优化 UV Charts 的布局有利于减少 dynamic lightmap 的大小,从而提高计算速度,是 Realtim GI 的重要优化策略。 UV Charts 场景视图模式可帮助您识别需要 UV 或缩放比例调整的几何图形(使用 “Lightmap Parameters” 中的 “Resulotion” 参数更改比例,或者更改 Indirect Resolution 来全局调整)。 此视图在调整 Realtime Lightmap 分辨率时也很有用。 每个 UV Charts 都有不同的颜色。Clustering
这显示的是 Enlighten 从
Lightmap Static
物体中生成的Clustering
。 Enlighten 在 5/11Clustering
阶段生成Clustering
,被用于计算间接照明。Clustering
的数量由 Lightmapping Settings 的Indirect Resolution
和 Lightmap Parameters 中的Cluster Resolution
参数控制。这个过程非常耗费内存和烘焙时间,如果您看到高内存使用甚至报错或烘烤时间过长,这可能是因为场景中的静态几何体被切割成比实际需要的更多的Clustering
。你可以通过使用更低级别的 Lightmap Parameters,或者适当降低Indirect Resolution
来解决该问题。Baked Lightmap
这显示了应用于场景物体的烘焙光照贴图。 棋盘格显示烘焙的 Lightmap 分辨率。该视图可以帮我们看到场景各物体占用的 lightmap 像素,通过调整场景的
Lightmap Resolution
和物体的Scale In Lightmap
来优化 Baked GI 的效果,这是 Baked GI 重要的优化策略。重要的光效明显的地方,我们应该分配更多的像素,而像一些小的物体,照明不明显的物体,要减少其分辨率,以最大程度地利用 Lightmap 的空间。有时,我们还可以选中物体,在 Lighting 窗口的 Object maps 栏中可以检查该物体的 Baked Charting,看是否充分利用其空间,有必要时可导回 3D MAX 等软件重展第二套 UV。关于 Chart,上文已经提过。可以理解成,Chart 就是物体在 lightmap 中属于自己的那一部分四方形区域。
Light Overlap(Shadowmask Overlap)
还记得 Shadowmask 模式有一个限制吗?一张 Shadowmask 贴图最多支持记录 4 个灯光的阴影遮蔽信息。超出的部分将会被烘焙到 lightmap 中。
这种模式可以让你看到所有的静态灯是否已经被烘焙到了 Shadowmask 上。 如果一个区域被四个以上的静态灯点亮,则超出的灯将退回到完全烘烤状态并显示为红色。下面屏幕截图中,最右边的聚光灯就是多出的,其阴影信息将被烘焙到 lightmap 中去。
后记
全局光照的库存文章到这里结束了,自从进了某厂就没怎么碰过 Unity,不过如果大家有兴趣进一步学习,可以留言给我,大家一起进步。 > 本文由简悦 SimpRead 转码