1

我正在阅读有关加载 DDS 纹理的信息。我读了这篇文章,看到了这个帖子。(我还阅读了关于 S3TC 的 wiki

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

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?为什么我们8DXT116其他人使用?

  2. 当我们计算时到底发生了什么size?更具体地说,为什么我们要加3,除4然后乘blockSize

  3. 为什么我们要乘以2if mipMapCount > 1
4

1 回答 1

2

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

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

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

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

(i + m - 1) / m * m

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

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

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

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

于 2015-11-01T11:13:30.223 回答