烘培场景中的光

渲染光照的过程是非常消耗新能的。即使是目前最好的[state-of-the-art]1GPU,要准确的计算 光的运动(light transport) [是指光在物体表面之间反射]也要花好些小时。 为了在游戏中让这个过程可行,光的实时渲染是必须要有的。如今的游戏引擎会在画面和效率上采取一个合理的折中方案;大部分的计算都在一个叫 光烘焙(light baking) 过程中事先计算好了。这一个知识点将会讲解光烘焙是如何工作的并且你该如何充分的利用它。


  • 始前准备

    光的烘焙需要你先准备一个场景。里面要有一些几何体,当然光也一定要有。这个知识点我们会基于Unity的标准特性,所以没有必要创建新的着色器或者材质。为了更好的控制这个过程,你可能需要访问 Lighting 窗口。如果你没有看见这个窗口,可以通过菜单 Window | Lighting 打开,并且停靠到一个你方便使用的位置。


  • 操作步骤

    光的烘培需要一些自定义的配置。你需要做三个必要的独立步骤。

    • 场景中静态几何体的配置

      配置的时候必须按照下面的步骤:

      1. 确认好你的场景中所有不会改变位置,大小和材质的游戏物体。一般可能的是建筑物,墙,地形,道具,树木等等。
      2. 在场景中选择这些类型的游戏对象,并且在 检查器面板(Inspector tab) 中勾选 Static 这个勾选框,就如下图所示。如果任何一个被选择的对象有子对象,Unity编辑器会询问是否想把这些子对象也作为静态对象。如果它们也满足(固定的位置,大小和材质),则在弹出的对话框中选择 是,子对象也变为静态(Yes change children)

      diagram

      1. 如果想让光照即影响静态游戏对象又影响非静态游戏对象,请确认把 Baking 属性设置为 Mixed 。如果只希望影响到静态游戏对象,那么把它设置为 Baked

    • 光探针的设置

      在你的游戏场景中有些游戏对象是会移动的,比如主角,敌人和 NPC(non-playable characters) 。如果它们进入了一个被照亮的静态区域,那么你也许想要放置一些光照探针在他们的周围。为了做到这些,请按下面的操作步骤走:

      1. 在编辑器菜单中,依次选择 GameObject | Light | Light Probe Group 。一个名为 光探针组(Light Probe Group) 的新游戏对象就出现在 检查器面板(Inspector tab) 中了。
      2. 一旦你选中这个光探针组,八个相互链接球体会出现。点击选中它,并且在场景中移动它,让它尽可能把你的角色会进入的静态区域围起来。 下图展示的就是如何用光照探针把静态的办公区域空间给围起来的例子:

      diagram 3. 选择会进入光照探针区域的移动游戏对象。 4. 在 检查面板(Inspector tab) 中,展开 渲染组件(renderer component) [通常是 网格渲染器(Mesh Renderer) ] 并且确认 Use Light Probes 这个选项被勾选了(如下图所示):

      diagram

      决定什么时候和什么情况下去使用光照探针是一个很关键的问题;关于此的更详细信息会在 原理介绍 部分介绍。


    • 光的烘培

      请按照下面的步骤进行光照的烘焙:

      1. 终于到了烘焙光照了,打开 光照(Lighting) 窗口并且选择 光照贴图面板(Lightmaps tab)
      2. 如果 自动(Auto) 勾选框勾选了,Unity编辑器将会在后台自动执行烘培过程。如果没有勾选,那就自己点击 Build 按钮手动烘培。

    注意 即使是为相对较小场景进行光的烘培也可能会花费几个小时。如果你不断移动静态游戏对象或者光线,Unity就会从头开始光的烘培过程,这会让Unity编辑器的运行异常的慢。你可以在通过窗口Lighting | Lightmaps取消勾选 Auto 的勾选框来阻止Unity自动烘培,这样你就可以手动开始这个烘培过程。


  • 原理介绍

    光线的传输是渲染中最复杂的部分。 在这个阶段中,GPU会计算光线是如何在物体之间反射的。 如果一个游戏对象和它所在的光线环境不会变化,那么这个计算可以只计算一次就行了,因为在游戏中它们永远都不会变化。把游戏对象标记为 静态(Static) 就是告诉Unity可以做上面说的那样的优化。

    笼统的讲,光照的烘培是关于静态游戏对象的全局光照的计算过程并且把计算的结果保存在一个叫 lightmap 的数据文件中。当烘培过程结束后,Lightmaps 就可以在 Lighting 窗口中的 Lightmaps 页签中找到:

    diagram 光的烘焙会消耗大量的内存。其实这是给这些静态表面贴上了新的纹理,这些纹理包含了光照信息。让我们想象一下,假如我们有一片森林,森林中所有的树木都共享同一个纹理。当我把这些树木都设置为静态对象,这样每一棵树都会有它独有的纹理【前面共享纹理的一部分】。 可想而知,如果不思考而无差别的使用光的烘焙,不仅会增加游戏的大小,还会大量增加内存对纹理的消耗。

    在这个知识点中要讲的另一个方面是 光探针(Light probing) 。光的烘焙可以为静态的几何图形生成质量非常高的光照结果,但是对于运动的物体却不行。如果你的游戏角色正在进入一个静态的区域,那么他看起来跟环境就有种莫名其妙的割裂感。 它们的阴影跟周围看起来并不匹配,导致整体的美术表现看起来不尽人意。还有另外一些物体,比如一些带蒙皮的网格渲染器,即使把它们设置为静态物体,它们也不会受到全局光照的影响。所以在实时渲染中使用烘焙光照是不可能的,所以我们需要 光照探针这个有效的替代方案。每一个光照探针会在空间中的一个特殊点对全局光照进行采样。而一组光照探针就可以在空间中的多个点采样,这样的话就可以在一个特殊的空间中修改全局光照。这样我们在移动的物体上就可以投射更好的光照表现, 即使全局光照仅仅是计算了仅有的几个点。有个很重要的点是记得用这些光照探针把这个特殊的空间包裹起来,这样光照探针才能起作用。最好把这些光照探针放在光照条件经常突然发生变化的区域。和光照贴图一样,光照探针也会增加内存的消耗, 同时摆放的位置也要巧妙。记住,它只为非静态图形存在。

    尽管我们使用了光照探针,但在Unity的全局光照中我们仍然有些方面没有讲到。比如说非静态物体不能在其他物体上反射光线。

  • 相关补充

    你可以从下面的连接中阅读关于光照探针的更多额外内容

    http://docs.unity3d.com/Manual/LightProbes.html


  1. 注意这并不是指某个具体的GPU,而是指目前位置最好的GPU,参考翻译来自于 state-of-the-art Model,并不是特指某个具体的模型,而是指在该项研究任务中,目前最好/最先进的模型 ↩︎