带 Alpha 通道的纹理(Direct3D 9)

可通过两种方法对纹理映射进行编码,这些地图表现出更复杂的透明度。 在每个情况下,描述透明度的块位于已描述的 64 位块之前。 透明度表示为每个像素 4 位的 4x4 位位图(显式编码),或者具有更少的位和线性内插,类似于用于颜色编码的内容。

透明度块和颜色块按下表所示排列。

Word 地址 64 位块
3:0 透明度块
7:4 前面所述的 64 位块

 

显式纹理编码

对于显式纹理编码(DXT2 和 DXT3 格式),描述透明度的纹素的 alpha 组件在 4x4 位位/纹素中编码。 这四位可以通过各种方式来实现,例如分流或使用 alpha 数据的四个最重要位。 但是,它们被生成,就像它们一样使用,没有任何形式的内插。

下图显示了 64 位透明度块。

64 位透明度块关系图

注意

Direct3D 的压缩方法使用四个最重要的位。

 

下表说明了每一个 16 位单词的 alpha 信息如何布局在内存中。

此表包含单词 0 的布局。

阿尔法
3:0 (LSB*) [0][0]
7:4 [0][1]
11:8 [0][2]
15:12 (MSB*) [0][3]

 

*最小有效位,最大有效位 (MSB)

此表包含单词 1 的布局。

阿尔法
3:0 (LSB) [1][0]
7:4 [1][1]
11:8 [1][2]
15:12 (MSB) [1][3]

 

此表包含单词 2 的布局。

阿尔法
3:0 (LSB) [2][0]
7:4 [2][1]
11:8 [2][2]
15:12 (MSB) [2][3]

 

此表包含单词 3 的布局。

阿尔法
3:0 (LSB) [3][0]
7:4 [3][1]
11:8 [3][2]
15:12 (MSB) [3][3]

 

DXT2 和 DXT3 之间的区别在于,在 DXT2 格式中,假定颜色数据已被 alpha 预乘。 在 DXT3 格式中,假定颜色不是 alpha 预乘的。 这两种格式是必需的,因为在大多数情况下,使用纹理时,只是检查数据不足以确定颜色值是否已乘以 alpha。 由于在运行时需要此信息,因此两个 FOURCC 代码用于区分这些情况。 但是,用于这两种格式的数据和内插方法是相同的。

DXT1 中用于确定纹素是否透明的颜色比较不采用此格式。 假设没有颜色比较,颜色数据始终被视为在 4 色模式下。 换句话说,DXT1 代码顶部的 if 语句应为以下内容:

if ((color_0 > color_1) OR !DXT1) {

Three-Bit 线性 Alpha 内插

DXT4 和 DXT5 格式的透明度编码基于类似于用于颜色的线性编码的概念。 两个 8 位 alpha 值和一个每像素三位的 4x4 位位图存储在块的前 8 个字节中。 代表性的 alpha 值用于内插中间 alpha 值。 其他信息以存储两个 alpha 值的方式提供。 如果alpha_0大于alpha_1,则内插会创建六个中间 alpha 值。 否则,在指定的 alpha 极端之间内插四个中间 alpha 值。 另外两个隐式 alpha 值为 0(完全透明)和 255(完全不透明)。

下面的代码示例演示了此算法。

// 8-alpha or 6-alpha block?    
if (alpha_0 > alpha_1) {    
    // 8-alpha block:  derive the other six alphas.    
    // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
    alpha_2 = (6 * alpha_0 + 1 * alpha_1 + 3) / 7;    // bit code 010
    alpha_3 = (5 * alpha_0 + 2 * alpha_1 + 3) / 7;    // bit code 011
    alpha_4 = (4 * alpha_0 + 3 * alpha_1 + 3) / 7;    // bit code 100
    alpha_5 = (3 * alpha_0 + 4 * alpha_1 + 3) / 7;    // bit code 101
    alpha_6 = (2 * alpha_0 + 5 * alpha_1 + 3) / 7;    // bit code 110
    alpha_7 = (1 * alpha_0 + 6 * alpha_1 + 3) / 7;    // bit code 111  
}    
else {  
    // 6-alpha block.    
    // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
    alpha_2 = (4 * alpha_0 + 1 * alpha_1 + 2) / 5;    // Bit code 010
    alpha_3 = (3 * alpha_0 + 2 * alpha_1 + 2) / 5;    // Bit code 011
    alpha_4 = (2 * alpha_0 + 3 * alpha_1 + 2) / 5;    // Bit code 100
    alpha_5 = (1 * alpha_0 + 4 * alpha_1 + 2) / 5;    // Bit code 101
    alpha_6 = 0;                                      // Bit code 110
    alpha_7 = 255;                                    // Bit code 111
}

alpha 块的内存布局如下所示:

字节 阿尔法
0 Alpha_0
1 Alpha_1
2 [0][2] (2 个 MSB)、[0][1]、[0][0]
3 [1][1] (1 MSB), [1][0], [0][3], [0][2] (1 LSB)
4 [1][3], [1][2], [1][1] (2 个 LSB)
5 [2][2] (2 个 MSB)、[2][1]、[2][0]
6 [3][1] (1 MSB), [3][0], [2][3], [2][2] (1 LSB)
7 [3][3], [3][2], [3][1] (2 个 LSB)

 

DXT4 和 DXT5 之间的区别在于,在 DXT4 格式中,假定颜色数据已被 alpha 预乘。 在 DXT5 格式中,假定颜色不是 alpha 预乘的。 这两种格式是必需的,因为在大多数情况下,使用纹理时,只是检查数据不足以确定颜色值是否已乘以 alpha。 由于在运行时需要此信息,因此两个 FOURCC 代码用于区分这些情况。 但是,用于这两种格式的数据和内插方法是相同的。

DXT1 中使用的颜色比较,以确定纹素是否透明,不用于这些格式。 假设没有颜色比较,颜色数据始终被视为在 4 色模式下。 换句话说,DXT1 代码顶部的 if 语句应为:

if ((color_0 > color_1) OR !DXT1) {

压缩纹理资源