使用 Unity 进行移动游戏照明

照明是游戏最重要的方面之一。它可以设定气氛,引导玩家,识别威胁或目标等等。照明可以成就或破坏游戏的视觉效果。例如,良好的照明可以让糟糕的模型在游戏中看起来更好,而糟糕的照明可以让优秀的模型看起来更糟糕。

本指南提供了有关在移动游戏中提高照明性能的信息。你如何决定使用照明会影响移动游戏的性能。有效地使用照明以确保游戏尽可能流畅地运行非常重要。

本文部分内容基于 Arm Limited 贡献和版权的作品。

渲染管线选项

Unity 的旧版渲染管线包括以下渲染路径

  • 前向渲染
  • 延迟着色

前向渲染

对于前向渲染,实时灯光非常昂贵。如果你减少每个像素存在的灯光数量,就可以抵消此成本。

延迟着色

延迟着色需要 GPU 支持。在兼容的硬件上,延迟着色可以渲染大量实时灯光,并具有高水平的照明保真度。不幸的是,延迟着色在移动 GPU 上的性能不佳,因为它们的带宽较低。

当你制作移动游戏时,重要的是你的游戏能够在尽可能多的设备上流畅运行。

通用渲染管线

Unity 开发了 通用渲染管线 (URP)。我们强烈建议你将 URP 用于移动游戏。

灯光模式

根据灯光在场景中的移动方式或使用方式,使用不同的灯光模式。灯光模式类型具有不同的性能特征。当你实现灯光时,请考虑以下几点

  • 对于静态照明,使用烘焙。这最适合在运行时不会更改其照明的对象。烘焙灯光是预计算并将照明数据存储在称为 光照贴图 的纹理贴图中的过程。
    • 烘焙照明在运行时无法修改。光照贴图中的灯光和阴影是静态的。由于所有照明都在 Unity 中进行了预处理,因此没有任何运行时照明计算会影响性能。
    • 无法使用烘焙灯光创建动态阴影。对于动态或移动对象,这可能看起来很奇怪。
  • 对于打算与移动对象交互的固定灯光,使用混合。例如,一个火把照射到玩家身上并在玩家经过时产生阴影。
    • 混合照明创建动态直接光和阴影。
    • 你可以将混合照明包含在静态对象的灯光贴图计算中。
    • 你可以在运行时更改强度。仅更新直接光。
    • 昂贵。
  • 对于动态或可移动灯光,例如从地面升起并爆炸的火球发出的光,使用实时
    • 动态灯光和阴影属性可以在运行时修改。
    • 实时灯光不会烘焙到光照贴图中。
    • 非常昂贵。

有关更多信息,请阅读 Unity 的照明管线

在可能的情况下,使用静态光并避免动态光

动态或实时照明在每一帧中都会计算和更新。这对于移动对象、交互性和创造情感非常有用。

相反,静态光信息被烘焙到光照贴图中。光照贴图纹理的使用使对象能够避免昂贵的每个顶点或每个像素照明计算。光照贴图纹理的渲染成本始终比动态照明便宜得多。我们建议将烘焙照明作为在移动游戏中实现的首选方法。

光照贴图烘焙

光线效果的预计算称为光照贴图烘焙。光线的效果存储在称为光照贴图的单独纹理中。光照贴图可用于增强对象的外观。光照贴图烘焙只需要对场景的每次迭代执行一次。如果更改场景的几何体或更改烘焙灯光的参数,则需要重新烘焙光照贴图。除了光照贴图纹理的开销之外,运行时没有任何额外的性能成本。这是在移动平台上进行照明的最佳初始方法。

烘焙灯光不受场景中任何动态或移动方面的影响。烘焙照明包括 烘焙全局照明,适用于所有静态元素。这意味着光照贴图计算包括从其他静态物体反射的间接光,以及直接照射到物体的烘焙灯光。

图 1. Armies 技术演示中使用的全烘焙照明设置。

要烘焙灯光,请执行以下三个步骤。

步骤 1:将灯光设置为混合或烘焙

将灯光的模式设置为混合或烘焙。对于移动游戏,最好使用烘焙灯光而不是混合灯光。烘焙是渲染灯光的成本最低的方式。

图 2. Unity 中灯光的模式设置。

步骤 2. 使对象静态

使受烘焙灯光影响的任何对象都静态。对于标记为静态的对象,有很多优化,但通常最好在静态下拉列表中选择全部。通过将对象标记为静态,Unity 就会知道将其包含在灯光烘焙中。

图 3. 静态菜单示例。

步骤 3. 烘焙灯光

你可以使用窗口 > 渲染 > 照明设置中找到的照明菜单来烘焙灯光。

当你烘焙灯光时,保存的数据基于你在开始烘焙时处于活动状态的场景。将生成一个与烘焙场景同名的文件夹。此文件夹存储照明数据的所有组件。如果你的项目同时加载多个场景,则必须为每个场景烘焙灯光。如果调整场景,则必须重新烘焙灯光。

图 4. 烘焙光照贴图示例。

优化光照贴图

在将灯光设置为烘焙后,请确保已优化烘焙的贴图。光照贴图的大小根据烘焙时的设置而有所不同。你必须降低移动设备上的内存使用量,因此必须监控光照贴图的大小。

在 Armies 演示的以下示例中,有七个 1024x1024 像素的光照贴图。在地图预览中,你可以看到叠加在光照贴图上的网格。选定的网格会突出显示。

图 5. 这是一个光照贴图示例。蓝色部分是选定的网格。

光照贴图设置中有很多设置以及贴图的大小,这些设置决定每个贴图使用多少内存和存储空间。以下部分重点介绍了一些重要的设置。

光照贴图生成器

Unity 提供以下三种方法来烘焙场景中的灯光

  • Enlighten:仅支持到 2020 长期支持 (LTS) 版本。不要在新项目中使用此功能。
  • 渐进式 CPU:节省大量时间,因为它会增量创建光照贴图。如果选择了优先级视图,则会优先处理场景视图中的区域。这可以减少设置场景光照的迭代时间。
  • 渐进式 GPU:此功能的工作原理与渐进式 CPU 相同,但会在 GPU 上而不是 CPU 上生成光照贴图。在支持的硬件上,此方法与使用 CPU 相比可以大大减少烘焙时间。设置渐进式 GPU 还有一些其他要求。有关要求的更多信息,请访问渐进式 GPU 光照贴图页面。

图 6.光照贴图设置允许您更改场景的烘焙方法。

纹素

纹素或纹理像素是纹理贴图中的单个像素。纹素在光照贴图中存储每个光点照射到物体上的光照信息。每个空间单位使用的纹素越多,照明质量、烘焙计算时间、磁盘存储成本以及光照贴图的 VRAM 成本都会受到影响。

要减少所需的光照贴图数据量,请在光照贴图设置中调整每个烘焙单元的纹素数量。

图 7.光照贴图的可用设置。

光照贴图设置中,光照贴图分辨率参数控制光照贴图中每个单位使用的纹素数量。以下是用不同光照贴图分辨率设置的立方体的示例。您可以看到,更高的分辨率会迅速增加所需的工作量。

图 8.第一个立方体的光照贴图分辨率1。第二个立方体的光照贴图分辨率2。第三个立方体的光照贴图分辨率5

要查看纹素在场景中的布局方式,请选择场景视图上的绘制模式下拉列表,然后选择烘焙光照贴图

烘焙对象覆盖有棋盘格叠加。棋盘格图案显示烘焙灯光时纹素的分布方式。

在以下示例中,在 Armies 演示中将光照贴图分辨率15降低到12,使所需的光照贴图数量从 7 个减少到 4 个。

图 9.光照贴图分辨率为12的 Armies 演示。

纹素使用情况

虽然您可以为整个场景设置每个单位的纹素数量,但通常有些对象不需要那么多纹素。

Unity 允许您控制每个对象使用的纹素数量。在对象的检查器 > 网格渲染器中,光照贴图缩放参数值控制对象在光照贴图中使用的纹素数量。

在以下示例中,左侧的立方体每个烘焙单元有 5 个光照信息纹素。右侧的立方体将其光照贴图缩放设置为 0.5。该设置将光照纹素缩放至 2.5,这比左侧的立方体所需的的光照贴图空间更少。

图 10.两个具有不同光照贴图分辨率的立方体。

图 11.您可以更改光照贴图缩放设置,使对象具有更少的纹素。

尝试避免在以下方面花费纹素

  • 玩家看不到的表面和物体。这可以防止在屏幕上没有的细节的光照贴图上浪费内存。
  • 表面上的光照变化很少。例如,阴影中的物体或被单个光源照射的物体。
  • 小物体或薄物体。它们接收到的光照量不会对场景的最终渲染产生太大影响。

尽可能模拟光照

为了降低处理要求,您可以模拟某些元素。这可以让您的内容看起来使用了光照,但实际上使用了更有效的方法。

模拟阴影

实时阴影成本很高。它们是使用称为阴影贴图的技术生成的。将场景几何体渲染到阴影贴图的成本与启用阴影绘制的顶点数成正比。建议您限制投射阴影的几何体数量和实时阴影投射灯的数量。

您可以为没有动态灯光的动态对象实现模拟阴影。这可以降低渲染成本,并可以达到与动态阴影类似的效果。以下是一些实现模拟阴影的方法

  • 使用 3D 网格(例如平面或四边形)放置在角色下方,并对其应用模糊纹理。
  • 您可以编写自己的自定义着色器以获得更复杂的斑点阴影。

以下示例显示了如果您使用 3D 网格作为阴影的结果

图 12.Armies 技术演示中的阴影实现。

直接在纹理上绘制光照信息

如果将一些阴影绘制到纹理中,则可以减少额外灯光所需的计算量。这在烘焙场景灯光时可以节省内存,因为它需要更少的光照贴图数据。

光照探针

当您将动态对象与烘焙灯光一起使用时,它们不会受到光照贴图的影响。这可能导致它们感觉不像是场景的一部分。

您可以使用光照探针解决此问题。光照探针与光照贴图具有类似的优势。它们存储可以提前计算并保存以供在运行时使用的光照数据。这将大部分计算成本转移到编辑时间。

光照贴图对表面的每个纹素接收到的光进行编码,而光照探针存储穿过空旷空间的光。您可以使用此数据来照亮移动的物体。光照探针有助于在整个场景中将动态物体与光照贴图物体在视觉上融合在一起。

光照探针最适合用于照亮场景中移动的物体。探针利用您的烘焙灯光,使您的移动物体与场景具有相同的光照。使用光照探针照亮动态物体比实时灯光更便宜。

您可以在使用光照探针进行静态照明光照探针页面上了解更多信息。

图 13.放置的光照探针用于照亮 Armies 技术演示中的动态人群。

网格渲染器设置

无论场景使用哪种类型的光照,正确设置网格渲染器设置都非常重要。

关闭不使用的任何内容。诸如投射阴影之类的设置即使在物体未被照亮时也会在渲染场景时增加成本。以下网格渲染器设置的示例适用于图 13 中显示的角色。该角色使用光照探针数据,但不使用反射探针。

光照探针的混合探针设置将来自最近光照探针的光照信息混合到角色中。当角色在场景中移动时,影响角色的光照探针会发生变化。投射阴影已关闭,因为渲染使用斑点方法。接收阴影也已关闭,因为场景已烘焙并且没有实时阴影。

图 14.图 13 渲染的网格渲染器设置。

实时灯光和灯光类型

建议您使用烘焙灯光光照探针和模拟光照技术(例如绘制的光照纹理或着色器材质效果)来处理灯光。但是,如果您需要实时灯光,则必须考虑要使用的灯光类型。

每种灯光类型的照明计算成本都不同。以下列表详细介绍了每种灯光类型

  • 方向光:此灯光具有统一的方向,没有衰减。方向光是最便宜的实时灯光。通常每个场景只需要一个方向光。对于移动设备建议的渲染路径前向渲染,如果场景中没有方向光,Unity 将包含一个默认的方向光。
  • 聚光灯:聚光灯会剔除其锥体外部的物体,并且不会照亮它们。这使得聚光灯的计算成本低于球形点光源。为了获得最佳性能,请保持锥体宽度窄,并且仅照射目标物体。
  • 点光源:这些灯光向所有方向投射光线。向所有方向投射的光很有用,但成本很高。点光源在较宽的区域内成本很高。此外,阴影计算可能是照明中最昂贵的部分。如果向所有方向投射光线,则会有更多阴影和更多计算。