Com2uS 使用 Vulkan 提升图形效果

Game title logo screenshot from Com2uS Chronicles.

召唤师战争:编年史 美国(全球)韩国 由 Com2uS 独家使用 Vulkan 在 Android 上进行渲染,性能提升高达 30%。

Vulkan 是一种现代的跨平台 3D 图形 API,旨在最大程度减少设备图形硬件和游戏之间的抽象。与 OpenGL ES 相比,Vulkan 的 CPU 开销更低,并且 Vulkan 提供了更广泛的功能。

图 1. 游戏截图。
图 2. 游戏视频。

渲染功能

Com2uS 为召唤师战争:编年史开发了高级渲染功能,包括

  • 具有预渲染光剔除的自定义延迟渲染系统,以及在视锥体中同时最多 16 个活动光源
  • 间接渲染实例化方法(称为Clay),用于一次绘制许多网格、材质和纹理
  • 广泛使用计算着色器进行预渲染任务
  • 能够根据相机移动、图形选项和运行时性能动态调整活动阴影渲染和后期处理效果

移动硬件适配

召唤师战争:编年史对 Android 设备、个人电脑和专用游戏主机使用相同的渲染器。为了在移动硬件上获得最佳性能,Com2uS 调整了渲染设置,包括绘制深度和密度。为了适应某些运行 Android 11(API 级别 30)及更低版本的设备,Com2uS 创建了一些着色器的替代版本,并使用了减少的实例数量。召唤师战争:编年史还在 Android 上使用自适应性能功能,以根据设备热状态动态调整图形选项。

仅使用 Vulkan 的原因

Com2uS 出于以下几个原因,在召唤师战争:编年史中独家使用 Vulkan

  • 最低设备要求排除了缺乏Vulkan 支持的旧版、性能较低的设备
  • 自定义Unity 引擎内置渲染管线 (BiRP) 需要游戏 Vulkan 后端中才有的功能
  • 利用计算着色器输出和着色器存储缓冲区对象 (SSBO) 实现渲染功能可以在 Vulkan 上完成,但在 OpenGL ES 上无法完成

计算工作负载

召唤师战争:编年史执行大量的计算着色器工作以生成渲染数据。计算着色器用于

  • 对象剔除
  • 碰撞检测
  • 动画任务
  • 间接渲染数据生成

计算得到的数据被写入 Unity 引擎的 RWBuffer 对象。为了实现最佳性能,召唤师战争:编年史 使用单次分派运行所有计算作业,这需要同时使用多个 RWBuffer。这种方法只有在使用 Vulkan 时才可能实现,因为 Unity BiRP OpenGL ES 后端一次只能支持使用一个 RWBuffer。

为渲染生成的数据集通常大于设备对统一缓冲区对象 (UBO) 的大小限制。召唤师战争:编年史 而是使用着色器存储缓冲区对象 (SSBO),它们具有更大的容量限制。但是,将 SSBO 绑定到顶点阶段操作需要只读 SSBO 支持。OpenGL ES 仅支持读写 SSBO,而 Vulkan 可以将 SSBO 标记为只读。

使用 Clay 进行间接实例化渲染

对于召唤师战争:编年史,Com2uS 开发了一种方法,将多个材质、网格和纹理批处理到单个绘制调用中。Com2uS 将此系统称为Clay。由于显着减少了绘制调用,Clay 使游戏性能提高了 30%。

Clay 在剔除和碰撞阶段开始,通过构建一个兼容的可视渲染对象列表。然后,Clay 将每个识别对象的渲染信息生成到 SSBO 中。此过程使用计算着色器执行,这使得能够使用 Unity 渲染器 DrawMeshInstancedIndirect 函数使用间接实例化渲染。通过间接渲染,实例信息和实例计数参数直接在 GPU 上生成。在绘制对象时,Clay 不是绑定传统的对象网格,而是绑定一个锥形网格,如图所示

图 3. 锥形网格。

然后,Clay 使用由计算着色器生成的绑定顶点变换数据的 SSBO 在顶点着色器中变换锥形网格。将 SSBO 绑定到顶点阶段需要使用 Vulkan。Clay 可以使用多个变换后的锥体来渲染单个对象。对象的复杂度决定了锥体的数量。

图 4. 锥形网格如何转换为树。

对象的材质数据在由计算着色器生成的另一个缓冲区中进行批处理。该缓冲区绑定到片段着色器。要绘制的对象的纹理在纹理数组中配置。对象的纹理的数组索引包含在对象的材质数据中。在理想情况下,Clay 可以最多使用七次绘制调用进行渲染

  • 静态对象
  • 动画对象
  • 阴影(四次迭代)
  • 反射

Unity 加 Vulkan

召唤师战争:编年史 演示了 Unity 游戏引擎和 Vulkan 图形 API 的强大组合,使开发人员能够将先进的控制台级图形带到 Android 设备上。