Textures with Alpha Channels

There are two ways to encode texture maps that exhibit more complex transparency. In each case, a block that describes the transparency precedes the 64-bit block already described. The transparency is either represented as a 4x4 bitmap with four bits per pixel (explicit encoding), or with fewer bits and linear interpolation analogous to what is used for color encoding.

The transparency block and the color block are laid out as follows:

Word Address 64-bit Block
3:0 Transparency block
7:4 Previously described 64-bit block

Explicit Texture Encoding

For explicit texture encoding (DXT2 and DXT3 formats), the alpha components of the texels that describe transparency are encoded in a 4x4 bitmap with 4 bits per texel. These 4 bits can be achieved through a variety of means such as dithering or by simply using the 4 most significant bits of the alpha data. However they are produced, they are used just as they are, without any form of interpolation.

Note  DirectDraw's compression method uses the 4 most significant bits.

The following tables illustrate how the alpha information is laid out in memory, for each 16-bit word.

This is the layout for Word 0:

Bits Alpha
3:0 (LSB) [0][0]
7:4 [0][1]
11:8 [0][2]
15:12 (MSB) [0][3]

This is the layout for Word 1:

Bits Alpha
3:0 (LSB) [1][0]
7:4 [1][1]
11:8 [1][2]
15:12 (MSB) [1][3]

This is the layout for Word 2:

Bits Alpha
3:0 (LSB) [2][0]
7:4 [2][1]
11:8 [2][2]
15:12 (MSB) [2][3]

This is the layout for Word 3:

Bits Alpha
3:0 (LSB) [3][0]
7:4 [3][1]
11:8 [3][2]
15:12 (MSB) [3][3]

Three-Bit Linear Alpha Interpolation

The encoding of transparency for the DXT4 and DXT5 formats is based on a concept similar to the linear encoding used for color. Two 8-bit alpha values and a 4x4 bitmap with three bits per pixel are stored in the first eight bytes of the block. The representative alpha values are used to interpolate intermediate alpha values. Additional information is available in the way the two alpha values are stored. If alpha_0 is greater than alpha_1, then six intermediate alpha values are created by the interpolation. Otherwise, four intermediate alpha values are interpolated between the specified alpha extremes. The two additional implicit alpha values are 0 (fully transparent) and 255 (fully opaque).

The following pseudo-code illustrates this algorithm:

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

The memory layout of the alpha block is as follows:

Byte Alpha
0 Alpha_0
1 Alpha_1
2 [0][2] (2 LSBs), [0][1], [0][0]
3 [1][1] (1 LSB), [1][0], [0][3], [0][2] (1 MSB)
4 [1][3], [1][2], [1][1] (2 MSBs)
5 [2][2] (2 LSBs), [2][1], [2][0]
6 [3][1] (1 LSB), [3][0], [2][3], [2][2] (1 MSB)
7 [3][3], [3][2], [3][1] (2 MSBs)