照明是游戏中最重要的方面之一。它可以营造气氛,引导玩家,识别威胁或目标等等。照明可以成就或破坏游戏的视觉效果。例如,良好的照明可以让糟糕的模型在游戏中看起来更好,而糟糕的光线可以让出色的模型看起来更糟。
本指南提供有关在移动游戏中提高照明性能的信息。您如何决定使用照明会影响移动游戏的性能。有效地使用照明以确保您的游戏尽可能流畅地运行非常重要。
本文的部分内容基于 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 将包含一个默认的方向光。
- 聚光灯:聚光灯会剔除其锥体外的物体,并且不会照亮它们。这使得聚光灯的计算成本低于球形点光源。为了获得最佳性能,请保持锥体宽度窄,并且仅照射目标物体。
- 点光源:这些灯光向所有方向投射光线。向各个方向投射的光线很有用,但成本很高。点光源在较广区域内成本很高。此外,阴影计算可能是照明中最昂贵的环节。如果向所有方向投射灯光,则会有更多的阴影和更多的计算。