ASTC纹理压缩格式详解

一、ASTC纹理压缩格式介绍

ASTC是在OpenGL ES3.0出现后在2012年中产生的一种业界领先的纹理压缩格式,它的压缩分块从4x4到12x12最终可以压缩到每个像素占用1bit以下,压缩比例有多种可选。ASTC格式支持RGBA,且适用于2的幂次方长宽等比尺寸和无尺寸要求的NPOT(非2的幂次方)纹理。

以ASTC 4x4 block压缩格式为例,每个像素占用1字节,8bits。一张1024*1024大小的贴图压缩后的大小为1M。

ASTC在压缩质量和容量上有很大的优势。

文档中有详细的测试数据:

Using ASTC Texture Compression for Game Assetsdeveloper.nvidia.com图标

二、适配机型

1、iOS

苹果从A8处理器开始支持 ASTC,iPhone6及iPad mini 4以上iOS设备支持,2014年的iPhone 5s及iPad mini 3以前的设备不支持。

2、安卓

安卓主流压缩格式正在从ETC2转向ASTC。

Unity官方对安卓ASTC格式支持的说明:

docs.unity3d.com/Manual

官方文档中提到GPU对ASTC的支持情况:所有支持OpenGL ES 3.1和部分支持OpenGL ES 3.0的GPU。

鉴于OpenGL ES 3.0 GPU的不确定性,我们对一些当前用户占比较高的低配机型进行了ASTC格式兼容性测试,并补充了一些占比低的GPU型号Mali-G71、Adreno 306、Adreno 308、Adreno 405做测试(测试时间2020.5.21):

市面上大部分机型都支持OpenGL ES 3.1以上,少数GPU配置较低的机型支持OpenGL ES 3.0但不支持ASTC压缩格式,在2020年4月统计的市面占比不到1.5%,从个人角度看ASTC压缩格式是可以普及使用的。

补充:Unity官方文档2018.4版本中有介绍对ASTC压缩格式的支持:docs.unity3d.com/2018.4

Texture Compression ASTC Platform Support:tvOS (all), iOS (A8), Android (PowerVR 6XT, Mali T600 series, Adreno 400 series, Tegra K1)

三、压缩比率的选择

前文我们了解了不同的ASTC格式的Bits Per Pixel(在本文中翻译为像素占用),为了更直观的感受,使用一张容易产生压缩失真的贴图进行示例。

1、ASTC与ETC2格式的压缩结果与容量对比

RGB8 vs ETC2 4bits vs ASTC 6x6

从上图可以看出,一张512x512尺寸的贴图(不带Alpha通道,开启Mipmap)的容量为1MB,压缩为ETC2 4 bits后容量为170.7KB,有明显失真,压缩为ASTC 6x6后容量为154.7KB,无明显失真,ASTC 6x6的容量小于ETC2 4 bits,压缩质量高于ETC2 4 bits。

ASTC 6x6 vs ETC2 4bits vs ASTC 8x8

从上图可以看出,压缩为ASTC 8x8后容量为85.4KB,容量约为ETC2 4 bits的50%,压缩质量高于ETC2 4 bits。

2、无Alpha通道,RGB 24 位/像素的压缩比率选择

ASTC 6x6 vs ASTC 8x8 vs ASTC 10x10

从上图可以看出,一张512x512尺寸的贴图(不带Alpha通道),压缩为ASTC 6x6、ASTC 8x8、ASTC10x10后均无明显失真,压缩为ASTC 8x8后容量与ASTC 6x6相比减小了约44.8%,压缩为ASTC10x10后容量与ASTC 8x8相比减小了约33.7%。

以法线贴图举例:

RGB8 vs ASTC 4x4 vs ASTC 5x5 vs ASTC 6x6

从上图可以看出,一张512x512尺寸的法线贴图,压缩为ASTC 4x4无明显失真,压缩为ASTC 5x5肉眼可见失真,压缩为ASTC6x6后明显失真。

以面部贴图举例:

从上图可以看出,压缩为ASTC 6x6无明显失真,压缩为ASTC 8x8后肉眼可见失真。

结论:无Alpha通道的贴图建议压缩格式为ASTC 8x8。如果贴图为法线贴图,建议压缩格式为ASTC 5x5。有更高要求的贴图(比如面部、场景地面),可以设置压缩格式为ASTC 6x6,法线贴图为ASTC 4x4。

结论与NV文档数据对比:

唯一有出入的地方是普通贴图的压缩选择ASTC 6x6还是ASTC 8x8,从个人角度,8x8的推荐指数应该为0。

3、带Alpha通道,RGBA 32 位/像素的压缩比率选择

ASTC 4x4 vs ASTC 5x5 vs ASTC 6x6

从上图可以看出,压缩为ASTC 5x5肉眼可见失真,压缩为ASTC 6x6后有明显失真,压缩为ASTC 5x5后容量与ASTC 4x4相比减小了约34.9%。在同一压缩格式下,带Alpha通道比不带Alpha通道的压缩质量下降明显。

结论:有Alpha通道的贴图建议压缩格式为ASTC 5x5。有更高要求的贴图(比如特效、UI),可以设置压缩格式为ASTC 4x4。

结论与NV文档数据对比一致:

4、有无Alpha通道对压缩的影响

在同一压缩格式下,贴图容量不变,有无Alpha通道对压缩结果有很大影响,带Alpha通道的贴图压缩质量下降。

从上图可以看出,对于带Alpha通道的32位图和不带Alpha通道的24位图,选择同一压缩格式时,压缩结果有很大差异。

对于一张带Alpha通道的32位图,选择Import Settings中的Alpha Source为None,压缩结果与不带Alpha通道一致。

5、其他问题

1)对Shader带来的影响

默认贴图是"black"时,如果贴图缺省,默认值是(0,0,0,0),A通道读取出来是0,使用RGB ETC2 4bits格式时,A通道读取出来是0,使用ASTC格式时,A通道读取出来是1。这里要注意Shader默认值的考虑。

2)JPEG格式已经是有损格式,在JPEG丢失的精度与ASTC压缩无关。

3)关于贴图尺寸。

压缩格式支持非2的幂次方时,只要硬件支持该压缩格式,就可以使用NPOT纹理。但是,2的幂次方纹理比其他尺寸更优,这里有复杂的图形学因素。

参考文章:zhihu.com/question/3769

简单的理解,贴图在GPU中是以块为单位存储的,为了尽可能节省内存和带宽,压缩格式对贴图也是分块存储的。在递归或循环时,如果一个数是2的幂次方,可以被2整除,而且商也是2的幂次方。OpenGL API支持非2的幂次方,是因为考虑到易用性隐藏了细节,在内部处理了一些必要的拉伸或填充操作。所以,在无特殊要求时,尽量使用POT纹理,并且制作时尽量按照实际应用尺寸来制作,避免一些高精度压缩到低精度使用的情况。

4)无论贴图本身是否带Alpha信息,ASTC压缩的不同设置直接决定压缩大小。控制贴图资源的包体大小,依赖于ASTC压缩格式的规范是否合理,毕竟压缩为ASTC 8x8后容量与ASTC 6x6相比减小了约44.8%(85.4KB vs 154.7KB),压缩为ASTC 8x8后容量与ASTC 4x4相比减小了约300%(85.4KB vs 341.4KB)。而我们通常检查Alpha通道是否为空,可以帮助我们判断Alpha的信息是否冗余,是否应该设置更低的压缩精度。

5)ASTC压缩的算法比较智能,它会为变化更大的通道RGB或者A分配更高的权重,而且对于单色图,RGB通道内容一样时,使用较低的像素占用就可以达到很好的效果。对于单色图完全没有必要使用R8压缩格式,而是应该将RGB通道填充一样的信息,选择ASTC较低的像素占比,如ASTC8x8。

6)在项目实际使用中发现,对于法线贴图,ETC2 4bits的压缩效果比ASTC 5x5好,对于带透明通道的贴图,存在ETC2 8 Bits比ASTC 4x4更优的情况,之前在测试中漏掉了对比,还需要进一步对比,根据实际情况进行选择。

编辑于 09-21

文章被以下专栏收录