一、压缩纹理

1996年,斯坦福大学Andrew Beers、Maneesh Agrawala和Navin Chaddha发表了一篇论文《Rendering from Compressed Texture》,提出了一种基于GPU的纹理压缩方法,GPU可以从该类型压缩纹理中直接采样并进行渲染,这种改进是巨大的进步:

  • 节省内存
    • 纹理在内存中是以压缩格式存在,不仅减小了文件大小,而且减小内存占用。
  • 减少传输,提升带宽
    • 图像数据不再需要由CPU解压缩再传输给GPU,而是可以在加载数据到内存时,一次性上传到GPU,然后由GPU进行解压采样,这可以减少客户端向GL服务端传输纹理数据的带宽。

      二、纹理压缩特点

      由于使用场景的差异,纹理压缩技术和一般的图像压缩技术有很大的差异:
压缩技术 图片压缩技术 纹理压缩技术
解压速度(解压速度) 不快
针对的是数据存储和传输
很快。
因为GPU要采样进行渲染,不能影响渲染速度。
压缩速度(编码速度) 不快 不快。
并不需要考虑纹理再压缩的情况,一般这个情况在程序之外完成。
访问速度 不快
最大化压缩比率,不同数据块可变压缩比率,读取某个数据可能需要解压一大块数据
随机访问。
纹理的任何位置随时都可能被访问
压缩比率、图像质量 可以有较高压缩比率。
无损压缩,不损失图像品质
有损压缩,高压缩比率

不同数据块,不同压缩比率
一般为有损压缩

固定压缩比率(采用索引,支持随机访问)

三、创建压缩纹理

压缩纹理和普通2D纹理的创建方法一样,这里可参照普通2D纹理的创建。区别就在于创建函数:

  • 普通纹理:glTexImage2D
  • 压缩纹理:glCompressedTexImage2D

    glCompressedTexImage2D

    ```cpp

void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);

// 创建一个压缩格式的二维纹理 // target: 指定纹理目标,可能值如下: // GL_TEXTURE_2D // GL_PROXY_TEXTURE_2D // GL_TEXTURE_1D_ARRAY // GL_PROXY_TEXTURE_1D_ARRAY // GL_TEXTURE_CUBE_MAP_POSITIVE_X // GL_TEXTURE_CUBE_MAP_NEGATIVE_X // GL_TEXTURE_CUBE_MAP_POSITIVE_Y // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y // GL_TEXTURE_CUBE_MAP_POSITIVE_Z // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // GL_PROXY_TEXTURE_CUBE_MAP // level: 纹理详细等级(level-of-detail),=0表示原始纹理大小,=1表示1/2原始纹理大小,以此类推 // internalformat: data存储的压缩图数据的格式 // width: 纹理像素宽度,2D纹理至少64,立方体(3D)纹理至少16 // height: 纹理像素高度,同上 // border: 必须是0 // imageSize: 从data地址开始的image data 的unsigned byte数 // data: 指向内存中压缩图像数据的指针

  1. <a name="nbsVC"></a>
  2. # 四、压缩纹理格式
  3. <a name="RmHz7"></a>
  4. ## 1、ETC(ETC1)
  5. Ericsson Texture Compression,爱立信公司于2005年提出的有损纹理压缩技术,OpenGL ES 2.0的标准,但并不是强制的,它是最通用的纹理压缩格式,几乎所有的移动设备都支持,它是一种为感知质量设计的有损算法,其依据是人眼对亮度改变的反应高于对色度的改变。<br />但是并不支持alpha通道,所以各大GPU厂商会支持ETC,但一般都会各自开发一套纹理压缩技术。
  6. ```cpp
  7. GL_OES_compressed_ETC1_RGB8_texture // 在 OpenGL ES 中扩展名
  8. GL_ETC1_RGB8_OES // 压缩24位RGB纹理,0.5bpp

原理:https://gameinstitute.qq.com/community/detail/123075

RGB ETC 4bit**

  • 每个像素占用4bit,对24位RGB数据提供了6:1的压缩比率,在OpenGL ES 2.0\3.0上支持,不支持alpha通道压缩,一般会采用以下方法解决这个问题:
    • 一张图片保存2个纹理:ETC压缩纹理+alpha可见的灰度图,然后自定义shader。
    • 两张图片:然后使用多重纹理技术(mipmaps)
  • 现在基本淘汰了,一般直接使用ETC2。

相关工具
ARM提供的工具Mali Texture Compression Tool。
这个工具可以解决ETC的不支持alpha通道问题,一种方法是在一个ETC纹理中保存两张纹理,一张RGB的ETC,一张alpha纹理(将alpha通道转换为可见的灰度图像),在自定义片段着色器,对纹理多做一个alpha采样。另一种方法是单独生成一张alpha通道的纹理,然后通过多重纹理技术(mipmaps)将两张纹理组合到一起。

2、ETC2**

OpenGL ES 3.0的标准,为强制标准,所有支持OpenGL ES 3.0的设备都支持ETC2,相比于ETC的优势:

  • 向下兼容ETC1
  • 比ETC1提供更好的纹理压缩质量
  • 支持alpha,支持单通道和双通道模式。

相比于其他纹理压缩技术(S3TC、PVRTC),压缩质量也更高,缺点是并不是所有的设备都支持OpenGL ES 3.0。

原理

RGB ETC2 4bit

  • 提供了和ETC相同的压缩比和功能,但压缩质量更高,在OpenGL ES 3.0上支持。

RGBA ETC2 8bit

  • 每像素8bit大小,支持8bit alpha通道。对32 bitRGBA提供了4:1的压缩比。

RGB+1 bit alpha ETC2 4bit

  • 每像素4bit大小,支持1bit alpha通道。

EAC

  • 核心原理与ETC相同,但它只用于单通道或双通道数据,OpenGL ES 3.0和OpenGL 4.3后的设备大部分支持,但由于安卓平台五花八门的兼容性,一般不建议用单双通道贴图。

    2、PVRTC

    参考资料:https://www.jianshu.com/p/d4e51dd55dfa**
    Power VR Texture Compression,由Imagination Technologies公司专为PowerVR显卡核心设计,支持的GPU为Imagination Technologies的PowerVR SGX系列。由于专利原因一般它只被用于苹果的设备,仅Iphone、Ipad和部分PowerVR的安卓机支持,有较高排他性。
    仅支持POT纹理,支持alpha通道,如果图像数据不含有alpha通道,则该通道空间会用于存储RGB数据,提升压缩比和质量。 ```cpp

GL_IMG_texture_compression_pvrtc; // 在OpenGL ES中的扩展名

GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; // 压缩24位RGB纹理,0.5bpp GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; // 压缩24位RGB纹理,0.25bpp GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; // 压缩32位RGBA纹理,0.5bpp GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; // 压缩32位RGBA纹理,0.25bpp

  1. **PVRTC2**<br />在GDC 2012上,Imagination TechnologiesPVRT进行了更新,推出了PVRTC2,增强了图像压缩质量,尤其是一些高对比度、大面积颜色不连续的部分、纹理边缘,支持NPOT纹理,更好地支持alpha预乘(Alpha Pre-Multiplied)。
  2. ```cpp
  3. GL_IMG_texture_compression_pvrtc2; // 在OpenGL ES中的扩展名
  4. GL_COMPRESSED_RGB_PVRTC2_4BPPV1_IMG; // 压缩24位RGB纹理,0.5bpp
  5. GL_COMPRESSED_RGB_PVRTC2_2BPPV1_IMG; // 压缩24位RGB纹理,0.25bpp
  6. GL_COMPRESSED_RGBA_PVRTC2_4BPPV1_IMG; // 压缩32位RGBA纹理,0.5bpp
  7. GL_COMPRESSED_RGBA_PVRTC2_2BPPV1_IMG; // 压缩32位RGBA纹理,0.25bpp

原理

PVRTC不同于DXT和ETC这类基于块的算法,而将整张纹理分为了高频信号和低频信号,低频信号由两张低分辨率的图像A和B表示,这两张图在两个维度上都缩小了4倍,高频信号则是全分辨率但低精度的调制图像M,M记录了每个像素混合的权重。要解码时,A和B图像经过双线性插值(bilinearly)宽高放大4倍,然后与M图上的权重进行混合。
https://gameinstitute.qq.com/community/detail/123075
https://zhuanlan.zhihu.com/p/237940807
https://www.khronos.org/registry/OpenGL/extensions/IMG/IMG_texture_compression_pvrtc2.txt

相关工具

Imagination Technologies提供了一套PVRTC格式工具,包括SDK、图形化工具PVRTexPool。可以借助工具生成PVRTC压缩纹理。
还有TexturePacker。

3、S3TC(DXTC)

S3TC:S3 Texture Compression
DXTC:DirectX Texture Compression

由 S3 Incorporated 公司在1999年申请的专利。后来被DX 6.0和OpenGL 1.3吸收为官方标准,因此S3TC也称DXTC,DXTC相当于Windows版的名字,S3TC是OpenGL中的名字。
支持的GPU为NVIDIA Tegra系列,在PC上广泛使用,移动设备商使用nVIDIA的很少。

  1. GL_EXT_texture_compression_dxt1; // 在OpenGL ES中的扩展名
  2. GL_EXT_texture_compression_s3tc; // 在OpenGL ES中的扩展名
  3. GL_COMPRESSED_RGB_S3TC_DXT1 // 压缩RGB纹理,0.5bpp
  4. GL_COMPRESSED_RGBA_S3TC_DXT1 // 压缩RGBA纹理,0.5bpp
  5. GL_COMPRESSED_RGBA_S3TC_DXT3 // 压缩RGBA纹理,1bpp
  6. GL_COMPRESSED_RGBA_S3TC_DXT5 // 压缩RGBA纹理,1bpp

原理

https://zhuanlan.zhihu.com/p/125751581

相关工具

可以使用DirectX SDK中自带的DirectX Texture Tool进行转换

4、ATITC

参考资料:https://huailiang.github.io/blog/2019/texture/

ATI Texture Compression。
支持的GPU为Qualcomm的Adreno系列,其他GPU厂商并不支持。

  1. GL_ATI_texture_compression_atitc // OpenGL ES扩展名
  2. GL_ATC_RGB_AMD // RGB,0.5bpp
  3. GL_ATC_RGBA_EXPLICIT_ALPHA_AMD // RGBA,1bpp
  4. GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD // RGBA,1bpp

相关工具

Adreno GPU SDK
Adreno Texture Tool

5、ASTC

参考资料

Adaptive Scalable Texture Compression,自适应可伸缩纹理压缩,由ARM和AMD联合研发,2012年发布,基于块的有损压缩算法,唯一一个不受专利影响的压缩格式,2018年被Khronos组织认可。
从IOS9开始支持 ,相对于PVRTC,ASTC(4X4)的压缩比会增加到0.25,显示效果也会好很多,而且不要求图片长宽相等且为2的幂次方,Android设备也支持,可以说,ASTC是目前最好的纹理压缩格式,默认首选。(由于这是最新压缩格式,所以可能存在部分机型不适配问题)

以2020年市场上的移动设备支持来看,推荐的纹理压缩格式如下:

  • android
    • ETC2:没什么问题。
    • ASTC:在Android 5.0/OpenGL ES 3.1后支持,市场上约98.5%的手机机型支持。
  • IOS
    • ASTC:iphone 6以上都支持。
    • PVRTC2:iphone 6以下选择。