加载 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;
什么是blockSize
?为什么我们对 DXT1
使用 8
而对其余的使用 16
?
我们在计算 size
时到底发生了什么?更多的
特别是为什么我们要添加 3
,除以 4
然后乘以
通过 blockSize
?
- 如果
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
这里,我们需要得到每个维度上的块数,然后乘以块的大小,得到纹理的总大小。为此,我们将 width
和 height
舍入到下一个 4 的倍数,除以 4 得到块数,最后乘以块的大小:
size = (((width + 3) / 4 * 4) * ((height + 3) / 4 * 4)) / 4 * blockSize;
// ^ ^ ^
如果你仔细看,有一个 *4 后跟一个 /4 可以简化。如果这样做,您将获得与之前完全相同的代码。所有这一切的结论可以是注释任何不是很明显的代码:P
3rd行可能是计算缓冲区大小的近似值,该缓冲区大小足以轻松存储整个 mipmap 链。但是我不确定这个 linearSize
是什么;它对应于 DDS header 中的 dwPitchOrLinearSize
。在任何情况下,您都不需要这个值,因为您可以使用上面的代码轻松计算每个级别的大小。
我正在阅读有关加载 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;
什么是
blockSize
?为什么我们对DXT1
使用8
而对其余的使用16
?我们在计算
size
时到底发生了什么?更多的 特别是为什么我们要添加3
,除以4
然后乘以 通过blockSize
?- 如果
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
这里,我们需要得到每个维度上的块数,然后乘以块的大小,得到纹理的总大小。为此,我们将 width
和 height
舍入到下一个 4 的倍数,除以 4 得到块数,最后乘以块的大小:
size = (((width + 3) / 4 * 4) * ((height + 3) / 4 * 4)) / 4 * blockSize;
// ^ ^ ^
如果你仔细看,有一个 *4 后跟一个 /4 可以简化。如果这样做,您将获得与之前完全相同的代码。所有这一切的结论可以是注释任何不是很明显的代码:P
3rd行可能是计算缓冲区大小的近似值,该缓冲区大小足以轻松存储整个 mipmap 链。但是我不确定这个 linearSize
是什么;它对应于 DDS header 中的 dwPitchOrLinearSize
。在任何情况下,您都不需要这个值,因为您可以使用上面的代码轻松计算每个级别的大小。