加载 DDS 纹理?

Loading DDS textures?

我正在阅读有关加载 DDS 纹理的信息。我读 this article and saw this posting. (I also read the wiki about S3TC)

我理解了大部分代码,但有两行我不太明白。

blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;

和:

size = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;

和:

bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
  1. 什么是blockSize?为什么我们对 DXT1 使用 8 而对其余的使用 16

  2. 我们在计算 size 时到底发生了什么?更多的 特别是为什么我们要添加 3,除以 4 然后乘以 通过 blockSize?

  3. 如果 mipMapCount > 1 为什么要乘以 2

DXT1-5格式也称为BCn格式(以数字结尾但不完全相同),BC代表块压缩。像素不单独存储,它只存储相当于4x4像素的数据块。

1st 行检查它是否为 DXT1,因为它的大小为每个块 8 字节。 DXT3 和 DXT5 每个块使用 16 个字节。 (请注意,存在较新的格式,其中至少一种是 8 bytes/block: BC4)。

2nd 将纹理的尺寸四舍五入为块尺寸的倍数。这是必需的,因为这些格式只能存储块,不能存储像素。例如,如果您有一个 15x6 像素的纹理,并且由于 BCn 块是 4x4 像素,您将需要每列存储 4 个块,每行存储 2 个块,即使最后 column/row 个块只部分填充。

将一个正整数(我们称之为 i)四舍五入为另一个正整数(我们称之为 m)的倍数的一种方法是:

(i + m - 1) / m * m

这里,我们需要得到每个维度上的块数,然后乘以块的大小,得到纹理的总大小。为此,我们将 widthheight 舍入到下一个 4 的倍数,除以 4 得到块数,最后乘以块的大小:

size = (((width + 3) / 4 * 4) * ((height + 3) / 4 * 4)) / 4 * blockSize;
//                         ^                        ^     ^

如果你仔细看,有一个 *4 后跟一个 /4 可以简化。如果这样做,您将获得与之前完全相同的代码。所有这一切的结论可以是注释任何不是很明显的代码:P

3rd可能是计算缓冲区大小的近似值,该缓冲区大小足以轻松存储整个 mipmap 链。但是我不确定这个 linearSize 是什么;它对应于 DDS header 中的 dwPitchOrLinearSize。在任何情况下,您都不需要这个值,因为您可以使用上面的代码轻松计算每个级别的大小。