一、ASTC纹理压缩格式介绍
ASTC是在OpenGL ES 3.0出现后,在2012年中产生的一种业界领先的纹理压缩格式,它的压缩分块从4x4到12x12最终可以压缩到每个像素占用1bit以下,压缩比例有多种可选。ASTC格式支持RGBA,且适用于2的幂次方长宽等比尺寸和无尺寸要求的NPOT(非2的幂次方)纹理。
以ASTC 4x4 block压缩格式为例,每个像素占用1字节,8bits。一张1024x1024大小的贴图压缩后的大小为1MB。
ASTC在压缩质量和容量上有很大的优势。
文档中有详细的测试数据:Using ASTC Texture Compression for Game Assets | NVIDIA Developer
二、适配机型
1. iOS
苹果从A8处理器开始支持ASTC,iPhone6及iPad mini 4以上iOS设备支持,2014年的iPhone 5s及iPad mini 3以前的设备不支持。
2. 安卓
安卓主流压缩格式正在从ETC2转向ASTC。
Unity官方对安卓ASTC格式支持的说明:
Unity - Manual: Recommended, default, and supported texture formats, by platform
官方文档中提到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压缩格式的支持。
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格式的压缩结果与容量对比
从上图可以看出,一张512x512尺寸的贴图(不带Alpha通道,开启Mipmap)的容量为1MB,压缩为ETC2 4 bits后容量为170.7KB,有明显失真,压缩为ASTC 6x6后容量为154.7KB,无明显失真,ASTC 6x6的容量小于ETC2 4 bits,压缩质量高于ETC2 4 bits。
从上图可以看出,压缩为ASTC 8x8后容量为85.4KB,容量约为ETC2 4 bits的50%,压缩质量高于ETC2 4 bits。
2. 无Alpha通道,RGB 24 位/像素的压缩格式选择
从上图可以看出,一张512x512尺寸的贴图(不带Alpha通道),压缩为ASTC 6x6、ASTC 8x8、ASTC 10x10后均无明显失真,压缩为ASTC 8x8后容量与ASTC 6x6相比减小了约44.8%,压缩为ASTC 10x10后容量与ASTC 8x8相比减小了约33.7%。
以法线贴图举例:
从上图可以看出,一张512x512尺寸的法线贴图,压缩为ASTC 4x4无明显失真,压缩为ASTC 5x5肉眼可见失真,压缩为ASTC 6x6后明显失真。
以面部贴图举例:
从上图可以看出,压缩为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 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的幂次方纹理比其他尺寸更优,这里有复杂的图形学因素。
参考文章:《OpenGL支持非二次幂纹理的底层原理是什么?》
简单的理解,贴图在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较低的像素占比,如ASTC 8x8。
6)在项目实际使用中发现,对于法线贴图,ETC2 4bits的压缩效果比ASTC 5x5好,对于带透明通道的贴图,存在ETC2 8 Bits比ASTC 4x4更优的情况,之前在测试中漏掉了对比,还需要进一步对比,根据实际情况进行选择。
A通道细节多的情况下,选择ASTC,A通道细节少的情况下,选择ETC2。
这是侑虎科技第1117篇文章,感谢作者Ssiya供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)
作者主页:Ssiya - 知乎
再次感谢Ssiya的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)