光照贴图过程将预先计算场景中静态物体表面的亮度,并将结果存储在称为“光照贴图”的纹理中供以后使用。光照贴图可以包含直接光照和间接光照,以及阴影效果。但是,烘焙到光照贴图中的数据无法在运行时更改,这就是为什么移动静态物体后,阴影不会跟随移动。接下来,我们就来演示如何使用光照贴图,我们新创建一个“LightDemo”的工程。在场景中我们创建了几个游戏对象,这些游戏对象的参数详细介绍如下截图所示:
以上是平面Plane的位置参数,它的材质颜色为(96,96,96,255),颜色为灰色系。
这是立方体Cube的位置参数,它的材质颜色为(185,131,13,255),颜色为橙色系。同时,我们调整主光源的位置和旋转方向,让其从Cueb的X轴右侧45度角照射下来,
请注意,光源的Z轴方向是照射的方向。
以上是两个球体Sphere的位置参数,他们的材质颜色为(135,73,159,255),颜色为紫色系。
当阳光斜射过来的时候,球体Sphere1处于立方体Cube的阴影之中。为了方便观察,我们还是修改一下相机的位置。首先,我们先调整Scene视图的角度,如下
大家可以看到,Scene视图和Game视图的角度是不一样的。我们保持Main Camera选中状态,然后点击菜单栏选择“GameObject”->“Align Width View”。该操作我们之前讲过,就是将Game视图的视角调整到当前Scene视图的视角。如下
两者保持一致了。接下来,我们Play运行一下,
请注意,我们的主光源“方向光”的模式为“混合”,既是实时光照也是烘焙光照。
光源模式设置确定后,我们需要对游戏对象进行一些设置,尤其是外部导入的3D模型。我们知道同一个模型可以使用多张贴图,但是模型的贴图需要UV坐标的支持,因此我们需要让我们的模型支持光照贴图UV。如何让我们的模型支持光照贴图UV呢?操作也非常简单,在“Project”视图中我们选择模型文件,然后在Inspector检视视图中的“Model”选项卡下面找到“Generate Lightmap UVs”,我们点击勾选这个项目即可,从名字上我们就可以得出,这是生成光照贴图UV坐标的意思。对于我们当前场景中的Cube,我们不需要进行此操作。
接下来,我们还需要将所有的游戏物体设置为静态物体(Static),在每个游戏对象的Inspector检视视图中,游戏对象名称右边的Static勾选框,我们点击勾选上,该游戏对象就成为一个静态物体了。在Unity中,物体是可以区分静态和动态的,如果一个物体是静止的,那么该物体在游戏中永远不会移动、旋转和缩放。注意,我们将地面Plane,立方体Cube和球体Sphere1设置为静态物体,而球体Sphere2保持默认的动态物体。
接下来,我们打开Lighting窗口(Window->rendering->lighting setting)。
首先,我们需要点击“New Lighting Settings”创建一个新的光照设置文件,该文件已经在上一章节中创建了,这里我们直接使用即可。在“Lighting Mode”选项一栏,我们选择“Subtractive”模式,也就是将静态物体的直接光照,间接光照和阴影全部烘焙到光照贴图中。在上述窗口的右下角有一个“Generate Lighting”按钮,就是生成光照贴图。点击开始生成光照贴图,等待一段时间后,就制作完毕了。请注意,烘焙的时间根据场景的复杂度不同而不同,我们的场景1-2分钟就结束了,真实地游戏场景可能需要很长很长的时间,几个小时,甚至几十个小时不等。
在上面截图中,Unity为我们生成了一张直接光照的光照贴图,尺寸为512*512像素,大小为2.7M左右。这个文件就位于Project工程面板的“Scenes/SampleScene”目录下
注意,光照贴图是与场景一一绑定的关系。也就是说,场景不一样,光照贴图是不一样的。因为光照贴图被存储到了以场景名称命名的文件夹下。我们在Scene窗口移动静态Cube后发现,它的阴影并没有跟随移动,说明光照贴图起作用了。如下所示
接下来,我们Play运行当前工程
其实没有任何的改变。接下来,我们在运行状态下(Game窗口)调整他们的位置,来查看光照产生的一些效果。静态物体不能在Game窗口下移动,因此我们只给动态物体球体Sphere2添加脚本,代码如下所示:
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
transform.Translate(Vector3.forward, Space.Self);
}
}
我们让Sphere2能够在自身Z轴方向能够移动,运行后效果如下
我们移动动态Sphere2后,发现阴影跟随移动,说明是实时光照其作用。但是,当我们移动Sphere2到Cube的阴影区域的时候,发现明显不对。Sphere2仍然是高亮的效果,它应该与Sphere1一样才对。因为动态物体不会受到光照贴图的影响。
为了让动态物体能够获得光照贴图信息,需要通过在场景中放置采样点将这些信息记录下来,并且在运行时能够让动态物体读取并使用。在Unity中,我们将这些采样点称为“light probe(光照探针)”。Light Probe主要解决了如何在动态物体上使用烘焙的照明信息。光照探针运行时效率非常高并且预计算也很快。接下来,我们就在场景中添加光照探针。
首先,我们菜单栏选择“GameObject”->“Light”->“Light Probe Group”游戏对象。
我们清楚的看到“Light Probe Group”,我们隐藏了其他游戏对象。操作方式就是,选中Light Probe Group”后使用快捷键Shift + H,就会进入Isolation 视图,该视图中只会显示当前选中的游戏对象。退出该视图也非常简单,再次使用快捷键Shift + H或者点击“Exit”退出。默认创建的“Light Probe Group”拥有八个光照探针(小黄球),并且组成一个立方体框架,每一个光照探针位于该立方体的一个顶点上面。我们来查看它的Inspector检视视图,
我们可以点击“Edit Light Probes”按钮来编辑这八个光照探针。你可以选中一个小黄球,移动重新摆放它的位置,也可以Delete键删除它。移动光照探针的操作与我们平时移动游戏对象是一样的。我们还可以选中一个光照探针,按Ctrl + D复制一个新的,然后移动这个新光照探针位置。那么,我们需要将这些光照探针移动到哪里呢?
我们点击“Edit Light Probes”进入编辑状态,然后点击其中一个黄色小球。我们可以选择X/Y/Z三轴来移动黄色小球。那么,我们需要将这些光照探针移动到哪里呢?光照探针是为了采集周围的“光照贴图”里面的光照数据。因此,我们需要将小球放置到Cube的阴影里面,用于获取阴影中的光照信息。这样,当Sphere2移动到阴影中的时候,就会受到阴影中的光照探针的影响。在游戏开发中,我们需要创建大量的光照探针(小黄球),我们该如何摆放他们呢?这里有一个简单的原则,为了提高光照探针的效率,应该在光照变化比较大的地方多放置光照探针,在光照变化不大的地方少放光照探针。比如应该在从明亮到阴影的过渡位置多放光照探针,在反射光较强烈的表面多放置光照探针,在大的平面上少放光照探针。这个道理应该很容易理解,光照探针并不是根据物理区域的大小来放置,而是根据光照信息的复杂程度来放置的。如果在一个很宽阔的区域,只有一个简单的平行光源照射,那么这个区域的光照信息基本是相似的,我们只需要一个或几个光照探针就足够了。总之,尽量让我们的动态物体能够处于我们光照探针的包围之中。一个场景中可以创建多个Light Probe Group游戏对象。目前,我们只需要做一些简单的移动即可,将8个小球放置阴影区域。
最后,我们需要重新烘焙一下。烘焙完成后,我们才能看见光照探头对场景中物体的作用。
烘焙过程中,我们就能看到“Light Probes”的信息了。我们重新Play当前工程,查看效果。
与之前的效果相比,我们的动态Sphere2不再那么明亮了,说明它受到了附近光照探针的影响,这样看起来比较真实一些了。Unity还提供了一个反射探针(Reflection Probe),当场景中不存在反射探针时,场景中带有反射的物体会直接反射天空盒产生的环境信息。当物体处于反射探针范围内时,该物体会反射反射探针范围内的环境信息。它的效果类似于我们日常生活中镜子的效果。这里不介绍了。