材质和着色器

请遵循以下最佳做法来优化 Android 游戏中材质和着色器的使用。

材质和着色器是现代 3D 美术的核心构建块。要想让 3D 游戏能够在尽可能多的设备上顺畅运行,首先要对 3D 美术进行精心设计,使其能够充分利用图形处理器。本指南重点介绍在移动设备上可对材质和着色器采取哪些优化措施和最佳做法来提高游戏性能并最大限度降低功耗。

本文中的部分内容基于由 Arm Limited 贡献并拥有版权的作品。

游戏引擎适合移动设备的着色器

不同的游戏引擎在关联材质和着色器的方式上不尽相同。Unity 引擎可以创建多个着色器,但每种材质只能分配有一个着色器。Unreal Engine 4 可以根据目标平台为材质应用不同的着色器。

有关着色器和材质的定义,请参阅适用于美工的材质和着色器最佳做法

如果您使用的是 Unity 或 Unreal Engine 4 等游戏引擎,请使用专为移动设备硬件而设计的内置着色器。这些着色器采用简化的功能实现方式,以提高在移动设备上的运行性能。如果可能,请在配置材质时关闭未在使用的功能。这些可能是像色调调节或细节贴图之类的功能。停用未使用的功能可使引擎在最终的着色器程序中省略它们,从而实现更高的性能。

Unity

Unity 包含多个渲染引擎。对于现代移动游戏,最佳选择是通用渲染管线 (URP)。URP 包含一组标准的着色器,这些着色器可以根据目标平台的不同自动调整复杂性。旧版 Unity 渲染程序包含一系列专为移动平台而设计的着色器。这些着色器被归入移动设备类别。

Unreal Engine 4

Unreal 引擎将根据选定的目标平台来选择移动设备着色器。移动设备着色器的视觉输出可能不同于默认的 Shader Model 5 着色器。您可以在 Unreal 编辑器中更改预览渲染级别,以模拟移动设备着色器的渲染输出。尽管存在一些差异,但 Unreal 在所有平台上使用相同的材质处理流程,因此移动设备着色器通常具有与默认着色器类似的视觉效果和行为。

在 Unreal 编辑器中设置移动设备预览渲染
图 1. 在 Unreal 编辑器中设置移动设备预览渲染。

最大限度地减少纹理采样器

针对移动设备的游戏应该在其材质中使用尽可能少的纹理。添加的每个纹理都需要额外的纹理采样,这样会消耗内存带宽并增加功耗。Unreal Engine 4 建议在移动设备上运行时最多使用 5 种材质纹理。即便是五个纹理采样器,若要在许多设备上广泛使用,开销也可能极其高昂。最大限度地减少纹理采样器数量的策略包括:

  • 使用纹理打包功能组合单通道纹理。如需详细了解这一方法,请参阅纹理指南。
  • 将粗糙度或金属性等参数的数据替换为数字常量,而不是从纹理中读取。
  • 使用非照亮着色器或简单的光照模型,以便能够省略在更复杂的光照模型中支持光照计算所需的纹理。

在可能的情况下停用光照

照亮与非照亮是着色器和材质的一种常见划分。实时光照涉及到着色器中的额外计算。根据当前采用的光照系统的类型,可能需要材质纹理,这样会使用更多的内存空间和带宽。对于移动游戏,特别是那些面向性能不太强劲的硬件的游戏,最大限度地减少实时光照的使用对于实现最佳性能非常重要。您应考虑设计美术方向,让您的设计能够在没有实时光照的情况下呈现出很好的效果,如风格化或卡通美术。

使用光照渲染与不使用光照渲染的模型对比
图 2. 使用实时光照渲染(左侧)和不使用实时光照渲染(右侧)的模型的示例。

最大限度地减少透明度的使用

应尽可能使用不透明材质。渲染具有透明度的对象总是比渲染同等不透明对象的开销更高。与计算机或游戏机图形硬件相比,移动设备图形硬件的设计使得渲染透明度的开销相对较高。在游戏中绘制许多透明对象时,特别是在相互层叠渲染时,会对性能产生负面影响。

在同一个像素上多次绘制是一个问题,称作“过度绘制”。应避免过度绘制多层透明度。很多游戏都有诊断工具能以可视化的形式直观显示过度绘制情况,以帮助检测和消除这个问题。使用这些工具可以提高游戏的性能,并找出导致帧速率降低的问题所在。

Unity 编辑器中的过度绘制可视化工具的示例
图 3. Unity 编辑器中的过度绘制可视化工具的示例。
Unreal 编辑器中的过度绘制可视化工具的示例
图 4. Unreal 编辑器中的过度绘制可视化工具的示例。

使用适当的 alpha 方法

实现透明度的最常见的方法是 alpha 混合和 alpha 测试。

alpha 测试将使对象材质看起来要么是 100% 不透明,要么是 100% 透明。您可以为这种抠图配置 alpha 值阈值。在 Unity 中,这种类型的透明度称为抠图。在 Unreal Engine 4 中,它称为遮罩混合模式。

alpha 混合允许对象材质具有一定的透明度,并且可使对象看起来部分透明。Unity 将这种类型的透明度称为透明。在 Unreal Engine 4 中,它称为半透明混合模式。

alpha 混合与 alpha 测试的比较
图 5. 使用 alpha 混合(中间)和 alpha 测试(右侧)渲染的示例图片(左侧)。

与 alpha 测试相比,alpha 混合通常可以生成更好的视觉外观。不过,对于某些类型的网格(如叶子),在运动中看网格时,alpha 混合可能看起来很奇怪。这是因为觉察到树叶和树枝是以错误的顺序渲染的。alpha 测试可以最大限度地减轻这种影响,但代价是树叶和树枝上会增加混叠和尖锐的边缘。

alpha 混合和 alpha 测试渲染同一个网格所需的时长可能不同。对于任意一种模式都能产生可接受的视觉输出的网格,您应进行基准测试,看看是否一种方法比另一种方法效果更好。

剖析着色器复杂性

纹理采样器、光照和透明度等渲染功能全部都会增加着色器复杂性并降低渲染性能。您可以使用游戏引擎中内置的工具以及外部图形工具来评估着色器复杂性。

Unreal Engine 4 包含一个着色器复杂性视图模式,用于为场景中的对象提供成本估算。

Unreal 编辑器中的“着色器复杂性”视图模式
图 6. Unreal 编辑器中的着色器复杂性视图模式。

您还可以使用 Unreal 的材质统计信息功能,在编制材质时剖析材质的成本。

Unreal 编辑器中的“材质统计信息”显示屏
图 7. Unreal 编辑器中的材质统计信息显示屏。

在顶点着色器中计算

渲染着色器计算通常在顶点着色器和片段(又称为像素)着色器之间进行分割。渲染的片段数通常大于顶点数。如果可以在顶点着色器中执行一项成本高昂的计算,则其运行频率将比在片段着色器中要低。

不过,如果此数据由片段着色器使用,则必须从顶点着色器进行传递。如果传输的数据量太大,在片段着色器中执行计算可能性能较高。您可以使用性能剖析工具来评估图层程序利用率,以确定一组计算的最佳着色器位置。Unreal Engine 4 具有自定义 UV 功能,可帮助执行此类性能分析。

避免成本高昂的数学运算

数学运算在着色器程序中用来控制着色器输出的行为和外观。常见的运算包括基本算术、幂、底数、对数等。数学运算的计算成本并不相等。如果着色器中充满成本高昂的运算,那么执行速度会较慢,特别是在旧款设备上。成本相对较低的运算示例包括:

  • 加法
  • 减法
  • 乘法

成本较高的运算包括:

  • 除法
  • 超越函数(正弦、余弦、幂、对数、正切)

经常剖析性能

您的性能瓶颈可能并不总是很明显。应避免假设问题所在,而是使用性能剖析工具来评估渲染性能。请确保在采用任何优化措施进行测试之前和之后这样做,以准确衡量其影响。