Com2uS 使用 Vulkan 提升图形效果

Game title logo screenshot from Com2uS Chronicles.

Com2uS 旗下游戏《召唤师战争:编年史US(WW)KR 版本在 Android 上独家采用 Vulkan 进行渲染,性能提升高达 30%。

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

图 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 设备上。