compression - 我认为 *.DDS 文件是为了快速加载?

标签 compression directx textures directdraw dds-format

好的,所以我正在尝试权衡使用各种不同纹理压缩技术的利弊。我花费了 99.999% 的时间为使用 DirectX 的 Windows 机器编写 2D Sprite 游戏。

到目前为止,我已经研究了带有 alpha 修整的纹理打包(SpriteSheets),这似乎是获得更多性能的一种不错的方法。现在我开始查看它们存储的纹理格式;当前,所有内容都存储为* .PNG。

我听说 *.DDS 文件很好,尤其是当与 DXT5(/3/1 取决于任务)压缩一起使用时,因为纹理在 VRAM 中保持压缩状态?人们还说,由于它们已经是 DirectDraw Surfaces,因此它们的加载速度也快得多。

所以我创建了一个应用程序来测试它;我调用低于 20 次的线路,在每次调用之间释放纹理。

    for (int i = 0; i < 20; i++)
 {
  if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"Test.dds", &g_pTexture ) ) )
  {
   return E_FAIL;
  }

  g_pTexture->Release();
  g_pTexture = NULL;
 }

现在,如果我使用 DXT5 纹理尝试此操作,则完成时间比加载简单的 *.PNG 需要 5 倍的时间。我听说如果你不生成 Mipmap,它会变慢,所以我仔细检查了一下。然后我更改了我用来生成 *.DDS 文件的程序,切换到 NVIDIA 自己的 nvcompress.exe,但没有任何效果。

编辑: 我忘了提到文件(*.png 和 *.dds)都是相同的图像,只是以不同的格式保存。 (相同的大小,阿尔法的数量,一切!)

编辑 2: 使用以下参数时,它的加载速度提高了近 2.5 倍,并且消耗的 VRAM 减少了很多!
 D3DXCreateTextureFromFileEx( g_pd3dDevice, L"Test.dds", D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_FROM_FILE, 0, D3DFMT_FROM_FILE, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, 0, NULL, NULL, &g_pTexture )

但是,我现在失去了纹理中的所有透明度,我查看了 DXT5 纹理,它在 Paint.NET 和 DirectX DDS 查看器中看起来不错。但是,当加载所有透明度时,它会变成纯黑色。色键问题?

编辑 3: 忽略最后一点,我太愚蠢了,在我的“快速示例”匆忙中,我忘记在 D3DXSprite->Begin() 上启用 Alpha-Blending。哦!

最佳答案

您需要区分文件存储在磁盘上的格式和纹理最终在视频内存中使用的格式。 DXT 压缩纹理在内存使用和视频内存质量之间提供了良好的平衡,但其他压缩技术(如 PNG 或 Jpeg 压缩)通常会产生更小的文件和/或更好的磁盘质量。

DDS 文件的优势在于它们直接支持 DXT 格式,并且以与 DirectX 期望数据在内存中布局相同的方式在磁盘上布局,因此在加载它们后将它们转换为格式所需的 CPU 时间最少硬件可以使用。它们还支持 PNG 等格式不支持的预生成 mipmap 链。将图像压缩为 DXT 格式是一个相当耗时的过程,因此您通常希望尽可能避免在加载时执行此操作。

带有预生成 mipmap 的 DDS 文件与您计划从中创建的视频内存纹理的大小和格式相同,将使用任何标准格式的最少 CPU 时间。您需要确保告诉 D3DX 不要执行任何缩放、过滤、格式转换或 mipmap 生成以保证这一点。 D3DXCreateTextureFromFileEx 允许您指定阻止任何内部转换发生的标志( D3DX_DEFAULT_NONPOW2 表示图像宽度和高度,如果您的硬件支持两个纹理的非幂, D3DFMT_FROM_FILE 防止 mipmap 生成或格式转换, D3DX_FILTER_NONE 防止任何过滤或缩放)。

CPU 时间只是故事的一半。如今,CPU 速度非常快,而硬盘驱动器相对较慢,因此有时如果您加载较小的压缩文件格式(如 PNG 或 JPG),然后执行大量 CPU 工作来转换它,则总加载时间可能会比加载较大文件时更短就像 DDS 一样,只需在视频内存中执行 memcpy。获得良好结果的一种常见方法是压缩 DDS 文件并解压缩它们,以便从磁盘快速加载并最大限度地降低格式转换的 CPU 成本。

PNG 和 JPG 等压缩格式将比其他图像更有效地压缩某些图像。 DDS 是固定压缩比——给定的图像分辨率和格式总是会压缩到相同的大小(这就是为什么它更适合在硬件中解压)。如果您使用简单的非代表性图像进行测试(例如统一的颜色或简单的图案),那么您的 PNG 文件可能非常小,因此从磁盘加载的速度会比典型的游戏图像更快。

关于compression - 我认为 *.DDS 文件是为了快速加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1460579/

相关文章:

C++ 和 SDL 纹理不会加载,但 SDL_GetError() 不会返回任何内容

iPhone OpenGL ES 纹理单元

java - 如何用 Java 打印 tar.gz 文件的内容?

compression - 使用 --rsyncable 选项使 zstd 压缩文件为 'rsyncable',就像 gzip 所做的那样

directx - Direct2D Direct3d11 互操作 - 设备会丢失吗?

microsoft-metro - 将 C++ AMP 与 Direct2D 结合使用

c# - 使用 C# 进行文件压缩的​​最佳方法

android - 如何减少移动使用的 mp3 流媒体流量消耗?

c++ - 重新解释将 IDXGISwapChain** 指针转换为 IUKnown** 指针

windows - 在配备 GeForce 960M 的笔记本电脑上初始化 D3D12 调试接口(interface)失败