初次接触贴图压缩概念时难免会有一个疑问——为什么不直接用JPEG之类的图像压缩算法来压缩贴图,还要研究出一大堆五花八门的压缩格式?这是因为贴图压缩可以在离线期间完成,一般不优先考虑效率,但解压需要实时在GPU上执行,对效率有非常高的要求,所以一个可用的贴图压缩方案需要具备以下特点:
解压算法必须简单、易于硬件实现
为了支持随机访问,访问单个像素需要解压的数据量不能太大,理想情况是和GPU的Bus width一样大,1个时钟周期即可将数据从VRAM传输到GPU进行解压,也可以更充分地利用GPU缓存
尽可能少的访存次数,访存的代价通常都比较高,尤其是间接访存
可以接受的压缩率和图像质量
为了满足上述条件,目前普遍采用一种叫做Block Compression的压缩方案。
JPEG为什么不能满足贴图压缩的需求:压缩时会用到DCT和Entropy Encoding,解压时必然要做IDCT和Entropy Decoding,这太过复杂,硬件实现起来也很困难。
Real-Time DXT Compression(实时DXT压缩)是一种广泛应用于游戏和图形应用中的纹理压缩技术。DXT(S3 Texture Compression)格式通过将纹理数据压缩为较小的块,显著减少显存占用,同时保持相对较高的图像质量。以下是关于Real-Time DXT Compression算法的详细介绍,包括其工作原理、步骤和实现细节。
DXT压缩格式概述
DXT压缩格式主要有几种变体,其中最常用的是DXT1、DXT3和DXT5:
- DXT1:支持RGB颜色,使用1位的透明度(可选),适合不需要透明度或简单透明度的纹理。
- DXT3:支持RGBA颜色,使用4位的透明度,适合需要高质量透明度的纹理。
- DXT5:支持RGBA颜色,使用3位的透明度,提供比DXT3更好的透明度处理。
Real-Time DXT Compression的工作原理
Real-Time DXT Compression的核心思想是将纹理数据分成小块(通常为4x4像素),然后对每个块进行压缩。以下是算法的主要步骤:
1. 块划分
将输入的纹理图像划分为4x4像素的块。每个块包含16个像素的数据。
2. 颜色选择
对于每个块,选择两个主要颜色(最亮和最暗的颜色),这两个颜色将用于生成块内的所有颜色。具体步骤如下:
- 计算最小和最大颜色:遍历块内的所有像素,找到RGB值的最小和最大值。
- 插值生成颜色:根据最小和最大颜色生成4个插值颜色(包括最小和最大颜色),形成一个颜色表。
3. 颜色索引生成
每个像素的颜色将被映射到上述生成的颜色表中的一个颜色。通过以下步骤生成颜色索引:
- 计算每个像素的颜色与颜色表的距离:使用简单的距离度量(如欧几里得距离)来确定每个像素最接近的颜色。
- 生成索引:为每个像素分配一个索引值(0到3),指向颜色表中的颜色。
4. 透明度处理(对于DXT3和DXT5)
- DXT3:使用4位的透明度值为每个像素分配透明度。透明度值可以直接存储在压缩数据中。
- DXT5:使用3位的透明度值,采用插值方法生成透明度表。
5. 数据打包
将颜色和透明度信息打包成压缩格式。DXT1、DXT3和DXT5的打包方式略有不同,但通常包括:
- 4字节存储两个主要颜色。
- 2字节存储颜色索引。
- 透明度信息(对于DXT3和DXT5)。
6. 输出压缩数据
将压缩后的数据输出为DXT格式,供GPU使用。
实现细节
- 并行处理:在GPU上实现时,可以利用GPU的并行计算能力,针对每个块并行执行压缩操作。
- 内存对齐:确保数据在内存中的对齐,以提高访问速度。
- 优化算法:可以通过使用快速的颜色距离计算和插值方法来优化压缩速度。
总结
Real-Time DXT Compression算法通过将纹理划分为小块、选择主要颜色、生成颜色索引和打包数据等步骤,实现了高效的纹理压缩。其在GPU上的实现能够充分利用并行处理能力,显著提高压缩速度,减少显存占用,同时保持较高的图像质量。这使得DXT压缩成为游戏开发和实时图形应用中广泛使用的技术。