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,需要完成不同的阶段。 关于当前进程的信息显示在进度条的顶部。
进度条显示Unity 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的设置外,还需要对物体进行相应设置。 场景中的物体的Mesh Renderer组件也具有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/11Create Systems阶段,将根据物体的接近度和光照贴图参数自动将场景细分为多个System,换句话说,System即是共享相同的Realtime Lightmap的对象组。 这是为了在更新间接照明时,实现多线程和优化性能。 上图的可视化显示了不同颜色的System。
UV Charts
这显示了在Realtime GI进程的4/11Create 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,不过如果大家有兴趣进一步学习,可以留言给我,大家一起进步。