具有 Alpha 通道的纹理 (Direct3D 9)
有两种方法可用于对展现更复杂透明度的纹理贴图进行编码。 在每种情况下,描述透明度的块都在已描述的 64 位块之前。 透明度以 4 x 4 位图表示,其中每个像素具有 4 位(显式编码)或者具有更少位和线性插值(与用于颜色编码的值类似)。
透明数据块和颜色块的排列方式如下表所示。
字地址 | 64 位块 |
---|---|
3:0 | 透明数据块 |
7:4 | 之前所述的 64 位块 |
显式纹理编码
对于) (DXT2 和 DXT3 格式的显式纹理编码,描述透明度的纹素的 alpha 分量在 4x4 位位图中编码,每个纹素 4 位。 这些四位组可以通过多种方式实现,比如抖动或通过使用四个最高有效位的 alpha 数据。 但它们只能产生并且按本身用途使用,不得有任何形式的内插。
以下图表显示 64 位透明数据块。
注意
Direct3D 的压缩方法使用四个最有效位。
下表描述了 alpha 信息(16 位词)如何在内存中分布。
此表包含 Word 0 的布局。
Bits | Alpha |
---|---|
3:0 (LSB*) | [0][0] |
7:4 | [0][1] |
11:8 | [0][2] |
15:12 (MSB*) | [0][3] |
*最低有效位,最高有效位 (MSB)
此表包含第 1 个字的布局。
Bits | Alpha |
---|---|
3:0 (LSB) | [1][0] |
7:4 | [1][1] |
11:8 | [1][2] |
15:12 (MSB) | [1][3] |
此表包含第 2 字的布局。
Bits | Alpha |
---|---|
3:0 (LSB) | [2][0] |
7:4 | [2][1] |
11:8 | [2][2] |
15:12 (MSB) | [2][3] |
此表包含 Word 3 的布局。
Bits | Alpha |
---|---|
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 位图(每个像素为 3 位)保存在块的前八个字节中。 典型的 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 块的内存布局如下所示:
Byte | 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) {
相关主题