Com2uS 使用 Vulkan 提升图形效果

Game title logo screenshot from Com2uS Chronicles.

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

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

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

渲染功能

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

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

移动硬件适应性

《召唤师战争:编年史》使用相同的渲染器来适配安卓设备、个人电脑和专用游戏主机。为了在移动硬件上获得最佳性能,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。

为渲染生成的dataset 通常大于设备对统一缓冲区对象 (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 设备上。