【笔记】【百人计划】图形3.6 纹理压缩

1. 什么是纹理压缩

纹理压缩:是为了解决内存、带宽问题,专为在计算机图形渲染系统中存储纹理而使用的图像压缩技术。

1.1 图片与纹理

  • 图片格式
    • 图片格式是图片文件的存储格式,通常在磁盘、内存中储存和传输文件时使用。
    • 例如:jpg、png、gif、bmp等
  • 纹理格式
    • 纹理格式是显卡能够直接进行采样的纹理数据格式,通常在向显卡中加载纹理时使用。
  • 纹理管线
    • 纹理压缩格式基于块压缩,能够更快读取像素所需字节块进行解压所以支持随机访问。
    • 图片压缩格式基于整张图片进行压缩,无法直接实现单个像素的解析。
    • 图片压缩格式无法被GPU识别,还需要经CPU解压缩成非压缩纹理格式才能被识别。

image-20220824164504787

2. 常见纹理压缩格式

image-20220824164711622

2.1 非压缩格式

非压缩格式
RGBA8888(RGBA32) 一个像素32位,包含A通道(一个像素消耗4字节)
RGBA4444(RGBA16) 一个像素16位,包含A通道(一个像素消耗2字节)
RGB888(RGB24) 一个像素24位,无A通道(一个像素消耗3字节)
RGB565(RGB16) 一个像素16位,无A通道(一个像素消耗2字节)

2.2 压缩格式

DXTC

DXTC纹理压缩格式来源于S3公司提出的S3TC算法,基本思想是把4x4的像素块压缩成一个64或128位的数据块,优点是创建了一个固定大小且独立的编码片段,没有共享查找表或其他依赖关系,简化了解码过程。

  • DXT1(BC1)

    • 每个块有2个16位RGB颜色值(RGB565),代表了此4x4像素块中颜色极端值,然后通过线性插值计算出两个中间颜色值,16个2位索引值则表示了每一个像素的颜色值索引;
    • (索引2个极端颜色+2个计算中间颜色)
    • 适用于不具有透明度信息的贴图(或一位(0、1)透明信息-完全不透明或完全透明)
      • 有透明信息时,只计算一个中间颜色值,剩下的一个索引表示透明信息
    • 参照RGB24的压缩率-64/(24*16) =1/6
    • image-20220824165255015
  • DXT2/3(BC2)

    • DXT2/3与DXT1类似,表示颜色信息的64位数据块不变,另外附加了64位数据来表示每个像素的Alpha信息,整个数据块变为128位
    • 每个像素占用8位,0-3表示透明信息,4-7表示颜色信息
    • 压缩率(RGBA32):128/(32*16) = 1/4
  • DXT4/5(BC3)

    • DXT4/5与DXT2/3的差异在于其Alpha信息使用了线性插值,表示颜色信息的64位数据块依然不变,Alpha信息则由2个8位Alpha极端值和16个3位索引值组成。
    • 压缩率(RGBA32):128/(32*16) = 1/4
  • 在Unity内贴图类型选为法线后会采用DXTnm压缩格式(居于DXT5),该格式会把法线贴图R通道存入A通道,然后RB通道清除为1,这样可以将法线XY信息分别存入到RGB/A中分别进行压缩,以获得更高的精度,然后再根据XY构建出Z通道数据。

ATI1/2
  • ATI1

    • 为ATI公司开发的纹理压缩格式,也被称为BC4,其每个数据块存储单个颜色的数据通道,以与DXT5中的Alpha数据相同的方式进行编码,常用于存储高度图,光滑度贴图,效果与原始图像基本无差异;
    • 压缩率(R8):64/(8*16)=1/2
  • ATI2

    • 也被称为BC5,每个块中存储两个颜色通道的数据,同上以与DX5中Alpha数据相同的方式进行编码,相当于存储了两个BC4块。
    • 压缩率(RG16):128/(8*16)=1/2
  • 如果是在将法线存储在XY双通道中采用BC5格式压缩,由于每个通道都有自己的索引,因此法线贴图XY信息可以比在BC1中保留更多的保真度,缺点是需要使用两倍内存,也需要更多带宽才能将纹理传递到着色器中;

BC6/7

仅在D3D11级图形硬件中受支持,他们每个块占用16字节,BC7针对8为RGB或RGBA数据,BC6针对RGB半精度浮点数据,因此BC6是唯一一个可以原生存储HDR的BC格式

  • BC6是专门针对HDR图像设计的压缩算法,压缩比为1/6
  • BC7是专门针对LDR图像设计的压缩算法,压缩比为1/3
    • 该格式用于高质量的RGBA压缩,可以显著减少由于压缩法线带来的错误效果
ETC

DirectX选择了DXTC作为标准压缩格式,对于Opengl则选择了爱立信研发的ETC格式,几乎所有安卓设备都可以支持ETC压缩,所以其在移动平台上被广泛使用。

ETC与DXTC具有相同的特点,将4x4的像素单元压缩成64位数据块,并将像素单元水平或竖直朝向分为两个区块,每个像素颜色等于基础颜色加上索引指向的亮度范围。

image-20220824183152849

  • ETC1

    • 每个数据块分区中的4位亮度索引信息会从16个内置亮度表中获取当前像素单元对应的亮度表,每个像素的2位像素索引值可以从亮度表的四个值中选取对应的亮度补充值
    • 压缩率(RGB24):64/(16*24)=1/6
  • ETC2

    • ETC1的扩展,支持了Alpha通道的压缩,硬件要求Opengl ES3.0和Opengl4.3以上
  • 差别

    • ETC1要求长宽为2的幂次的贴图,适用于所有安卓设备,压缩率比较高,但不适合带Alpha通道的贴图
    • ETC2要求长宽能被4整除的贴图,设备有硬件要求,支持Alpha通道压缩,内存占用大于ETC1
ASTC

ASTC是ARM和AMD联合开发的纹理压缩格式,各项指标都不错,

  • 优点
    • 可根据不同图片选择不同压缩率的算法
    • 图片不需要为2的幂次
    • 同时支持LDR和HDR
  • 缺点
    • 兼容性不够完善
    • 解码时间较长

ASTC也是基于块的压缩算法,与BC7类似,数据块大小固定为128位,不同的是块中像素数量可变,从4x4到12x12像素都有。

每个数据块中存储了两个插值端点,但不一定存储的是颜色信息,也可能是Layer信息,这样可以用来对Normal或Alpha进行更好的压缩

对于块中每个像素,存储对应插值端点的权重,存储的权重数量可以少于纹素数量,可通过插值得到每一个纹素的权重值,然后再进行颜色的计算。

  • 数据块构成
    • 11位:权重、高度信息、特殊块标识
    • 2位:Part数量
    • 4位:16种插值端点模式(如LDR/HDR,RGB/RGBA)
    • 111位:插值端点信息,纹素权重值,配置信息
PVRTC

由Imagination公司专为PowerVR显卡设计,仅支持Iphone,Ipad和部分安卓机。

不同于DXTC和ETC这类基于块的算法,PVRTC将图像分为了低频和高频信号,低频信号由两张低分辨率图像AB组成,高频信号则是低精度的调制图像,记录了每个像素混合的权重,解码时AB图像经过双线性插值放大,然后根据调制图像的权重进行混合

  • PVRTC
    • PVRTC 2-bpp(bit per pixel)
    • PVRTC 4-bpp把一个4x4的像素单元压缩成一个64位数据块,每一个块中存储一个32位(每个像素2位)的调制数据,一个1位的调制标识,15位(RGB555/RGBA4443)的颜色A,1位颜色A不透明标识(决定按照RGB还是RGBA进行存储),14位(RGB554/RGBA4433)颜色B,1位颜色B不透明标识
    • 压缩率(RGB):64/(24*16) = 1/6
    • 压缩率(RGBA):64/(32*16) = 1/8

2.3 总结

  • 画质比较
    • RGBA>ASTC 4x4>ASTC6x6>ETC2 ≈ETC1
  • 压缩比
压缩格式 压缩率
DXT1 1/6
DXT2/3 1/4
DXT4/5 1/4
ATI1 1/4
ATI2 1/4
BC6 1/6
BC7 1/3
ASTC 1/4~1/35.95
PVRTC 1/6

3. 实际应用中的选择

  • PC
    • 低质量使用DXT1,不支持A通道,使用DXT5格式支持A通道
    • 高质量使用BC7,支持A通道
  • 安卓
    • 低质量使用ETC1,不支持A通道
    • 低质量使用ETC2,支持A通道(Opengl ES3.0/Opengl 4.3以上版本)
    • 高质量使用ASTC(Android5.0/Opengl ES3.1以上版本)
  • IOS
    • 高质量使用ASTC(Iphone6以上版本)
    • 低质量使用PVRTC2(支持Iphone6以下版本)

作业

结合今天课程,针对ASTC与ETC2这两个格式进行打包测试,分析内存占用占比。

3.7的作业正好也差不多。。。放个链接

https://xzyw7.github.io/post/Lyp-tjMR_/#%E4%BD%9C%E4%B8%9A

(ASTC6x6&ETC2)最后包体的体积是非常接近的

image-20220824023612935

ASCT

image-20220824024417255

image-20220824024516591

ETC2

image-20220824024425619

image-20220824024506074

就包体而言ASCT6x6是更大一些的,但是最后的内存占用却小了一些。

(帧率的差别应该主要来源于CPU的性能差别,ASTC的CPU性能占用稍高,也就是解码的消耗)

image-20220824025009019

image-20220824025016354

再用单张贴图的压缩结果来看看各种压缩格式的效果(ASTC压缩实在是有点猛,相比也会占用更多CPU时间)

image-20220824021751226

image-20220824021823244

image-20220824021805123

image-20220824021840952

image-20220824021857439

参考资料

[1] https://www.bilibili.com/video/BV1Av411K7bt

【技术美术百人计划】图形 3.6 纹理压缩——包体瘦身术