带 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) {
相关主题