一种新的自适应可伸缩纹理压缩 (ASTC) 编解码器, 用于加速游戏中的纹理处理





5.00/5 (1投票)
纹理编码器和解码器通常是游戏中带宽占用最多的部分,而使用 ARM 的 ASTC 编码器进行优化编码可以为运行时解码带来诸多好处。
如今,AAA 级游戏很容易 在磁盘上拥有 20GB 或更多的纹理数据。如果您正在开发一款游戏,那么纹理很可能占用了您内存和磁盘预算的绝大部分。这种内存占用也会影响您的帧时间。更多的纹理数据意味着更大的硬件内存总线和 GPU 内存缓存消耗。
这种趋势似乎没有尽头。4k 和 8k 分辨率以及 HDR 支持显示器的日益普及,都在逼近。
那么,开发者该怎么办呢?
您很可能采用某种形式的压缩,而且不是一般的压缩。纹理需要快速上传到 GPU 并进行实时解码,才能有望保持紧凑的帧时间。因此,您可能会使用支持硬件解压缩的压缩纹理格式。常见的例子包括 BC1-7(块压缩)、ETC1-2(Ericsson 纹理压缩)、PVRTC(PowerVR 纹理压缩)或 ASTC(自适应可伸缩纹理压缩)。
最近,ARM 与关键游戏开发利益相关者合作发布了一款新的 ASTC 编码器,该编码器在性能已经很高的编解码器上显著提高了压缩速度。在本文中,我们将帮助您快速了解 ASTC 与其他纹理编解码器的区别以及为什么您应该使用它。然后,我们将向您展示如何将 ASTC 集成到您的游戏或引擎的纹理管道中。最后,我们将与当前常用的编码器进行压缩时间和质量方面的快速基准测试。
什么是 ASTC?
ASTC 是一种纹理压缩形式,它使用可变块大小,而不是单一固定大小。它是一种灵活的纹理压缩方案,同时使用 OpenGL ES 和 OpenGL 3D 图形 API。ASTC 是一项开放标准、免版税的格式规范,由The Khronos Group管理。
在深入了解 ASTC 的细节及其独特性之前,让我们先回顾一下像BC1这样的简单编解码器是如何工作的。
大多数硬件纹理编码器都是基于块的,这意味着源图像被细分为相邻的块,然后独立压缩。对于 BC1,图像被分成 4x4 的瓦片。每个块压缩为 8 字节,支持三个颜色通道和一个 alpha 位。使用 ASTC 和 BC1 等格式的纹理可以直接流式传输到 GPU,无需进行全图像解压缩。
如果只有三个颜色通道和一个 alpha 位,BC1 就够了,但如果您只有两个通道呢?如果您需要超过 1 位的 alpha 信息呢?如果您需要一个颜色通道比另一个颜色通道更高的精度,或者想压缩 3D 或体纹理呢?
如果您使用的是 BC 格式,那么其他的 BC 变体就派上用场了:BC3 到 BC7 支持您可能想在游戏中使用的各种纹理类型的各种排列。
ASTC 采取了不同的方法。
顾名思义,ASTC 是自适应的,因为单一格式可以支持 2D 或 3D、LDR 或 HDR(低或高动态范围渲染)以及一到四个通道的颜色数据。无论请求的组件数量如何,ASTC 纹素始终解码为 RGBA 值。此外,ASTC 块不需要是 2 的幂次方大小。事实上,它们甚至不必是方形的。
与 BC 格式相比,ASTC 最类似于 BC7。虽然较简单的编解码器使用固定模式编码,其中每个块通过选择两个颜色插值器并将权重分配给每个组成纹素来压缩,但像 ASTC 和 BC7 这样的编解码器可以选择性地分区每个块,因此不能用单个梯度准确表示的块可以表示为多个梯度。
此外,在选择存储在插值器中的信息方面,还增加了额外的自由度。ASTC 使用程序生成的查找表来存储分区分配,如下所示。解释 ASTC 编码方案的全部机制超出了本文的范围,但您可以在ASTC 格式概述中阅读更多内容。
为什么使用 ASTC?
如果您正在发布移动游戏,ASTC 有很多优势。截至撰写本文时,ASTC 支持 Apple 设备(使用 A8 芯片,首款于 2014 年推出)或更高版本,以及大量的 Android 设备(包括自 2014 年以来推出的大多数 GPU)。有关支持 ASTC 的设备的最新列表,请参阅 Unity 游戏引擎推荐纹理格式的文档。ASTC 还支持其他游戏引擎,例如虚幻引擎 4,并在 Nintendo Switch(NVIDIA Tegra K1 GPU)等其他消费类平台上提供硬件支持。
除了硬件支持之外,ASTC 相对于其他常用格式还有其他一些显著优势。如下图表所示,编码比特率非常灵活,比其他格式具有更强的压缩能力。
可配置模式可以以更高的质量编码蒙版和法线纹理。有 HDR 编码模式,包括支持 LDR 和 HDR alpha 的格式变体。此外,还支持体 3D 图像纹理——这值得注意,因为体纹理通常占用的空间很大,但这些体 3D 扩展是可选的,并且支持程度不如广泛(仅 Mali)。
ASTC 实践
在使用其他纹理格式时,学习曲线在于了解哪种格式适用于特定的纹理用途。例如,切线空间法线贴图通常编码为 BC5 纹理,因为它为两个向量分量提供了更高的精度(第三个可以在着色器中重新构造)。
相比之下,对于 ASTC,学习曲线在于理解单一自适应格式的配置。
压缩纹理时的基本设置包括颜色模式、块大小、质量和纹理用法(颜色、蒙版或法线)。
对于颜色模式,您可以选择使用线性 LDR(8 位量化颜色通道)、sRGB LDR(8 位量化颜色通道,带 sRGB gamma 编码)或 HDR(浮点颜色通道)。HDR 支持对于您在光照通道中采样(例如,天空盒)的纹理,或者您希望对其进行采样以直接输出到 HDR 显示器的纹理来说,是一项很棒的功能。对于 HDR,您还可以选择将 alpha 通道编码为 LDR 或 HDR。
ASTC 中的块大小也与其他纹理格式有显著不同。不仅块大小不是固定的,块大小甚至不一定是方形的。块占用的空间越大,压缩率越高,但请记住,压缩是有损的,所以您应该期望信号会下降。可用的块范围从 4x4(8 位/纹素,类似于 BC7)到 12x12(0.89 位/纹素)。对于移动游戏开发,6x6 和 8x8 块大小最受欢迎,在图像质量和带宽之间取得了良好的平衡。
质量设置允许您在压缩速度和图像质量之间进行权衡。这里的选项范围从最快(2K 纹理的压缩速度不到一秒)到穷尽(2K 纹理需要几十秒或更长时间)。
具有特殊用途的纹理,如切线空间法线贴图或材质蒙版,可以通过一些额外的可选标志进行编码。如果纹理被压缩为蒙版,这会告诉编码器源图像中的颜色通道存储不相关的数据,并且在选择良好编码时,不应将其视为颜色。这将产生更高的感知质量结果。
如果编码器被告知将 3 通道输入压缩为法线贴图,则压缩数据将包含两个更高精度的通道(X 和 Y),因为 Z 可以使用归一化条件在着色器中重新构造。
定义您的纹理管道
ARM ASTC 编码器是一款命令行工具,用于使用 ASTC 纹理压缩标准压缩和解压缩图像。它还可以用作库,供希望对其管道进行更多控制的用户使用。ARM 的新编码器 (astcenc 2.1) 比其前代产品 (astcenc 1.7) 快六倍,ARM 提供了一套有用的指南来使用该编码器。虽然您应该完整阅读 ARM 的文档,但这里有一些快速提示可以帮助您入门。
首先,为游戏中的所有纹理创建一个分类方案(例如,角色和风景纹理的低、中、高分辨率变体)。您需要足够的粒度来优化游戏的内存占用,但您不希望粒度太大,以至于艺术家抱怨选项太多!
对于每个分类,请考虑纹理编码的数据类型、纹理的相对重要性(例如,角色装备的漫反射图与树叶广告牌与粗糙度/金属度纹理)、最坏情况的绘制距离和最坏情况的光照条件。近距离和良好光照下看到的纹理需要更高的图像质量。
对于每个分类,确定所需的压缩率。考虑您的磁盘占用空间、所需的纹理数量以及您的预算,然后反向工作。之后,分析在该比特率下编码的代表性纹理的质量,以确定质量设置。请注意,特别是对于颜色纹理,您希望使用 sRGB 颜色空间以获得更好的感知质量。
最后,教会您的离线纹理管道如何消费您的纹理资产并使用正确的设置进行压缩(下一节介绍)。请注意,命令行编码器尚未自动生成 mipmap 链和最终打包,但它可以编译为库,允许开发人员提供自己的前端。要将命令行工具集成到您的管道中,您需要使用外部工具对图像进行下采样,并自行将压缩的输出打包到纹理文件中(例如,KTX)。请参阅 GitHub 上的跟踪问题:GitHub。
虽然这似乎有很多步骤,但它实际上与您需要对 BC 或 ETC 纹理格式系列进行的分析和分桶操作类似。这种管道的主要好处是灵活的质量设置和比特率,与具有固定比特率的其他纹理格式相比,可以最大程度地打包您的纹理数据。换句话说,前期投资可能会更高,但回报也更大。当然,如果您只是想快速上手,可以将初始分类方案定义得尽可能粗糙。
基准测试和使用 ASTC 编码器
为了进行实验,我们将使用一张 2K 的漫反射纹理,该纹理来自 textures.com 上的中世纪铺路地板材质。要进行跟进,以及将编码器集成到您自己的纹理管道中,您还需要编码器,它在 GitHub 上以二进制文件的形式分发。此外,您还需要其他工具,例如ImageMagick,将 TIFF 图像转换为 ASTC 编码器可以理解的格式,例如 PNG。
该版本实际上包含三个二进制文件,分别对应它们编译所依据的指令集。在本次演示中,我们将使用通过 AVX2(高级向量扩展)编译的二进制文件,以实现最大吞吐量。漫反射图像如下所示
要将其编码为 ASTC 纹理,请使用以下命令
astcenc-avx2.exe -cs albedo.png albedo.astc 4x4 -medium
此命令指定
- (-cs) 输入为 LDR sRGB 图像
- (4x4) 以 8.00 bpp 编码(4x4 块大小)
- (-medium) 平衡压缩速度和图像质量
此命令在 AMD Ryzen 9 3900X(24 核)上的编码时间为 3.94 秒,效果令人印象深刻。这是前后对比图,放大到右上角(左侧为源图像)。
即使在这个放大级别下,伪影也很少,与 BC7 的质量相当。在较低的质量设置和较大的块大小(右侧为 8x8)下,块伪影变得更加明显,但整个图像仍然保留了相当多的细节。
以下矩阵显示了几个代表性质量和块大小设置的压缩时间(可能会有一些误差)。
压缩时间 | 块大小 | ||
质量设置 | 4x4 (8.00 bpp) | 6x6 (3.56 bpp) | 10x10 (1.28 bpp) |
细致 | 7.519 秒 | 10.006 秒 | 11.012 秒 |
媒体 | 1.994 秒 | 2.489 秒 | 2.065 秒 |
快速 | 0.381 秒 | 0.305 秒 | 0.241 秒 |
如您所见,质量设置对压缩时间的影响通常比块大小更大。在我的测试中,编码器的速度比 AMD 的Compressonator在类似设置下的运行速度快四到八倍。有关 ASTC Encoder 2.0 相对于其前代产品 (astcenc 1.7) 性能改进的更多统计数据,Khronos 提供了一份有用的分析。此处显示的测量结果是在 2020 年 11 月 13 日的版本 (astcenc 2.1) 上进行的,该版本声称性能有了进一步的提升。
总结
如果您在移动设备上发布游戏或纹理密集型应用程序,ASTC 应该成为您管道中不可或缺的一部分。由于过去五年及更长时间内生产的移动设备广泛支持、可变的压缩率以及针对各种纹理格式和用途的高质量结果,ASTC 是一种引人注目的纹理格式。更快的编码器在确保被认为是纹理格式复杂度“最终 boss”的内容烹饪时间合理方面也取得了长足的进步。
要了解有关 ASTC 格式的更多信息,ARM 在编码器文档中提供了一个出色的可视化教程。更详细的关于各种 ASTC 块模式和压缩格式的规范来自The Khronos Group。最后,ARM 提供了全面的文档,包括最佳实践、ASTC 在流行游戏引擎中的使用、替代编码工具以及 ASTC 在运行时使用方面的信息。