我认为*.DDS文件应该是加载快速的吗?

4

好的,我正在尝试权衡使用各种不同的纹理压缩技术的优点和缺点。我花费99.999%的时间编写Windows机器上使用DirectX的2D精灵游戏。

到目前为止,我已经看过了使用alpha-trimming的纹理打包(SpriteSheets),这似乎是获得更高性能的不错方法。现在我开始研究存储它们的纹理格式;目前所有东西都以*.PNGs的形式存储。

我听说*.DDS文件很好,特别是在与DXT5(/3/1取决于任务)压缩一起使用时,因为纹理保持在VRAM中压缩?此外,人们说它们已经是DirectDraw表面,所以加载速度非常快。

因此,我创建了一个应用程序来测试它。我调用下面的代码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倍的时间才能完成。我听说如果不生成Mipmaps,速度会变慢,所以我仔细检查了一下。然后我更改了用于生成*.DDS文件的程序,改用NVIDIA自己的nvcompress.exe,但没有任何效果。
编辑:我忘记提到这两个文件(*.png和*.dds)都是相同的图像,只是以不同的格式保存。(大小、alpha数量等都相同!)
编辑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 Viewer中看起来很好。但是,当加载时,所有的透明度都变成了纯黑色。颜色键问题?

编辑3:忽略上面的内容,我很蠢,在我的“快速示例”中,我忘记在D3DXSprite->Begin()上启用Alpha-Blending了。天啊!

也许纹理被复制到视频内存中(非常慢),因此您不仅要测量纹理本身的加载时间。 - newgre
关于EDIT2的问题:“几乎比原来慢5倍”的速度快了近2.5倍,还是比PNG快2.5倍? - Axel Rietschin
2个回答

14

你需要区分硬盘上文件存储的格式和纹理在视频内存中使用的格式。DXT压缩纹理在视频内存中在内存使用和质量方面提供了良好的平衡,但其他压缩技术如PNG或JPEG压缩通常会产生更小的文件和/或更好的质量。

DDS文件具有支持DXT格式并且以与DirectX期望数据在内存中排布相同的方式排列在硬盘上的优势,因此加载后几乎不需要任何CPU时间将它们转换为硬件可用的格式。它们还支持预生成的mipmap链,而PNG等格式则不支持。将图像压缩为DXT格式是一个相当耗时的过程,因此通常应尽可能避免在加载时进行压缩。

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

然而,CPU时间只有一半的故事。现在的CPU速度相当快,硬盘相对较慢,因此有时候如果您加载一个较小的压缩文件格式(如PNG或JPG)并进行大量的CPU工作来进行转换,总体加载时间可能会更短,而不是加载一个较大的文件像DDS然后将其复制到视频内存中。一个常见的方法是将DDS文件压缩,并进行解压以实现快速从磁盘加载和最小化的格式转换的CPU成本。

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


谢谢Matt,你的回答非常出色。我已经编辑了我的原始帖子,提出了一个相关问题。 - Siyfion

1

比较加载标准PNG并压缩它所需的时间与加载DDS文件所需的时间。

我仍然不明白为什么PNG加载速度会比相同纹理DXT5压缩快。首先,它会小得多,因此应该更快地从磁盘加载!这个DXT5纹理和PNG纹理一样吗?它们的大小相同吗?

您尝试过使用D3DXCreateTextureFromFileEx进行操作吗?您可以更好地控制正在发生的事情。这可能会对您有所帮助。


抱歉,我应该提到正在加载哪些文件...我已经编辑好了以反映这一点。 - Siyfion
有没有可能看到那些纹理? - Goz
如果需要的话,可以这样做,但它们是标准的四倍大小的纹理精灵表,包含一个动画图像。 - Siyfion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接