Contents

贴图压缩格式

压缩格式

传统上完全不压缩的像素RGB8,一个像素需要24位。块压缩是一种有损纹理压缩技术,用于减小纹理大小并减少内存占用,从而提高性能。 块压缩纹理可以比每种颜色 32 位的纹理小。

一.BC压缩格式

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011145254.png

BC1

BC1是将一个块(4*4)内16个像素384进行压缩到64位.压缩比例可以达到6倍。

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011145746.png

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011142917.png

  1. 我们将选中块中所有颜色的极值,分别记为BaseColor0和BaseColor1。共占32位。
  2. BaseColor的格式因为从24位转为了16位的颜色会有精度问题,位数为RGB565格式。
  3. 根据两个BaseColor生成另外两个BaseColor颜色。这两个中间颜色是根据比例勾兑的
    1. BaseColor2 = 2/3 *BaseColor0 + 1/3 * BaseColor1
    2. BaseColor3 = 2/3 *BaseColor1 + 1/3 * BaseColor0
  4. 另外32位每个像素有两位的索引,用来进行BaseColor的组合。
  5. 如果Color0>Color1代表完全不透明的,反之有一位的透明信息。
  6. 如果判断有一位的透明信息,则去掉BaseColor3,BaseColor2= 1/2* BaseColor0 + 1/2* BaseColor1,BaseColor变为RGB555,多出一位作为透明度的记录。

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011153520.png

BC2

BC2 格式将具有相同位数和数据布局的颜色存储为 BC1 格式;但是,BC2 需要额外 64 位内存来存储 alpha 数据,如下图所示

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011145800.png

BC2的alpha使用的是4位,因此表达的alpha 的精度并不精确

BC3

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011150723.png

BC3用来压缩alpha值为8位的贴图,可以用来存储高度连贯的alpha数据。颜色值的存储是一致的,Alpha 的存储使用类似于颜色的插值方案来处理。

我们记录两个极值alpha0和alpha1。共16位,剩下的48位分给索引值,每个像素三位。如果 alpha0 大于 alpha1,则 BC3 内插 6个 alpha 值; 否则,它将内插4个alpha值。 当 BC3 仅内插 4 个 alpha 值时,它会设置两个额外的 alpha 值(0 表示完全透明,255 表示完全不透明)

BC4

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011151633.png

使用 BC4 格式存储单分量颜色数据(8 位) 相比,该算法在 4×4 纹素块上操作。16*8=128位。我们压缩成两个8位的的red (red0 和 red1)共16位,并且每个像素有三位的索引 16 *3=48位。一共64位,压缩率为50%。

如果red0 > red1,那么我们插值六个,否则插值四个,多出的索引值将代表完全透明或者不透明

BC5

存储双分量颜色数据

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011152342.png

二.ETC压缩(EricssonTexture Compression)

ETC在移动平台中广泛采用。它是一种为感知质量设计的有损算法,其依据是人眼对亮度改变的反应要高于色度改变。因此我们整个图像的亮度和色度分为不同的存储方案。

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011154126.png

ETC1

ETC最大的弊端是不支持Alpha通道的存储,不过在后续的ETC2中也得到了支持。

ETC1每4x4像素块编码为64位的字节数据。4x4的块被分成两个子块,垂直分(2x4)或者水平分(4x2)。对于每个子块而言,我们原始数据对于24位的RGB数据为192位,压缩为32位,提供6倍的压缩率。

ETC1里有两种模式:individual模式和differential模式。这两种模式决定了子块存储的颜色是以RGB444/RGB444(individual模式)还是RGB555/RGB333(differential模式)格式存储颜色的数据。并且我们有一个单独的修正表格进行亮度修正。

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011162400.png

也就是说,对于每个子块而言,使用12位记录一个基础颜色,然后每个像素有三位的索引值进行亮度修正。

  1. 当我们的模式是individual的时候每个子块的颜色都用RBG444存储。解压时需要扩展到24位(通过重复自己的四位拼接,高4位和低4位相同)。
  2. 当是Differential模式的时候,子块1以RGB555,子块2以RGB333方式存储。子块1的颜色是以5bit的高3位作为扩充为8位之后的低3位,子块2计算时,先要通过和子块1存储的RGB叠加。把RGB333转为RGB555,然后再扩充为RGB888。
  3. 当我们获取了每个子块的基础颜色就需要进行亮度修正,我们需要一个亮度修正表。根据修正表修正自己的亮度。

还有一种使用4*4类似的策略,思路是一致的。

ETC2

因为ETC2-RGBA是以44的Block为单位进行编码的,所以我们的压缩算法也以44的Block为单位来进行。

ETC2的RGB通道和A通道是单独分别进行压缩的,一个Block的128个bit中,两者各占了64bit。这里我们先考虑RGB通道的压缩。ETC2一个Block的RGB通道,可以从5种编码方式中选择其中一种,分别是:

  1. Individual模式
  2. T模式
  3. H模式
  4. Planar模式
  5. Differential模式

其中Individual模式和Differential模式是主要的两个模式,也是从ETC1开始就有的两个模式。而T模式、H模式、Planar模式是ETC2新增的3个模式,用于优化某些特殊情况下Block的压缩质量。考虑到实时压缩的性能要求,我们目前只使用了Individual模式和Differential模式。

我们现在考虑A通道的压缩。ETC2的一个Block内,A通道独自占据了其中64个bit。首先,每个Block使用了8个bit来存放A通道的基准值;然后,与RGB通道类似,A通道也有一个固定的偏移表,内容如下:

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011162349.png

可见这个偏移量表更大,精度更高。毕竟A通道独自占用了64个bit,空间更为充裕,有足够的bit来索引这个更大的表。A通道使用了4个bit来从这个偏移表中选择当前Block希望使用的偏移量范围。这里与RGB通道有个不同之处:从偏移表中选择了需要的行之后,还要乘以一个4bit的系数,才能得到真正的偏移量范围。4bit的系数是一个0~15的数字。

三. PVRTC

PVRTC的不是基于block的方式生成的,但是却也可以理解为以block方式组织的。其生成压缩后包含两张(w/4,h/4)大小的缩略图(w,h为原始图片的宽和高,可以理解为第4级的mipmap,但生成过程会比较mipmap的复杂),其中的每个pixel映射并对应到原始图像中的一个64x64的block上;然后使用1张与原始图像大小相同的modulate图,对应的每个pixel占2个bits,也即可对应四种调制方式,通过几种不同的调制方式还原出近似的原始像素值。

四.ASTC

与ETC相比,ASTC的设计更加灵活、优雅,所以我们很自然的将目光转向这里。ASTC使用了特殊的BISE编码(即Bounded Integer Sequence Encoding),能保证在任何情况下都不会有太多bit浪费;另外固定编码模式内其实有非常多的可选项,导致用户的自由度非常高但压缩算法的复杂度也与之俱增。

虽然由于赶不上GLES3的发布时机,没进入ES3标准,但如今几乎所有ES3设备都支持ASTC格式,普及率很高。跟大部分硬件压缩格式一样,ASTC也是block-based,但不像PVR/ETC等固定了block size的算法,ASTC的策略是每个block固定占用128bit,但block size可以从4x4(8bpp,即8 bits per pixel)去到12x12(0.89bpp),也就是说,12x12的ASTC,只有4x4的ASTC的1/9体积,伸缩性非常好。

虽然ASTC提供了数量庞大的可选项,但它的算法核心是不变的——本质也是一种基于插值的压缩算法——即对于每个block,需要记录两个(或2n个)颜色端点,对于其中的每个(或几个)纹素,记录它们的权重,在解压时进行线性插值得到结果。这种方式与基于平均值+扰动的ETC有着本质的区别。

全局选项需要预先指定,ASTC目前提供三个全局选项:

  1. block大小:这个选项其实是允许用户在压缩率和压缩质量之间做权衡,目前最常用的即4x4;
  2. block维度:有2D和3D两种选项,这里只考虑前者;
  3. 是否采用sRGB。

局部选项可以根据每个block的特征在压缩代码内灵活选择,ASTC目前提供8个局部选项:

  1. grid大小: grid是一个标识采样区域大小的变量。它的出发点是,如果要压缩一个基于12x12大小的block,那么每个纹素1bit都不够用,那么就只能对某些范围内的纹素赋统一的权重。
  2. 每个纹素权重的变化范围:代表了该block内的插值精度。但注意使用了BISE的ASTC可以取的范围和一般的压缩方式不同:一般的压缩方式可以取的范围都是2的幂,但BISE扩大了该范围,可以取到40、48等特殊值,提升了特定情况下的压缩精度。
  3. 每个纹素的权重值:该值基于BISE进行编码,范围由上面的选项决定。
  4. Partition个数:也就是划分,并不是ASTC首创的概念,它在面向PC的BC系列压缩算法中就已有所涉及。它的基本思想是,一个block内的颜色分布可能是很复杂的(比如红色的球放在绿色的草地上),因此单纯的端点插值效果可能不是很好,这时候我们可能需要指定多于一组的颜色端点进行插值。支持一个block内有最多4个划分(即4组颜色端点),但这些划分的pattern都是写死的,共计2^10=1024种

https://papalqiblog.oss-cn-beijing.aliyuncs.com/blog/picture20211011162927.png

  1. 颜色端点模式:ASTC支持各种各样的端点模式混合搭配,不同模式下各个通道的值精度不在可选项内,因为解码程序会自动计算前面所有配置还为这个部分剩下了多少bits,然后默认你选择了最优解。
  2. 颜色端点值:该值同样基于BISE进行编码,值的变化范围由解码程序计算求得。
  3. 平面个数:考虑一个四通道的情况:我们把四个通道看作了向量的四个维度进行插值,但有些时候这些通道并不存在相关性,这就会导致插值产生比较大的误差.
  4. 平面-通道映射:该选项指定了双面模式下,哪个通道会被单独插值

上述是官方文档中描述的8个选项和解释,但实际上ASTC还有一种名为void extent的模式,它只在一个block内所有纹素值全部相同时被采用,用以最大化颜色精度和加快解码速度。