DDS 编程指南

Direct3D 实现用于存储未压缩或压缩的 (DXTn) 纹理的 DDS 文件格式。 文件格式实现几种略有不同的类型,旨在存储不同类型的数据,并支持单层纹理、具有 mipmap、多维数据集地图、卷图和纹理数组(在 Direct3D 10/11 中)。 本部分介绍 DDS 文件的布局。

有关在 Direct3D 11 中创建纹理的帮助,请参阅 如何:创建纹理。 有关 Direct3D 9 中的帮助,请参阅 D3DX 中的 纹理支持(Direct3D 9)

DDS 文件布局

DDS 文件是包含以下信息的二进制文件:

  • 一个包含四个字符代码值“DDS”(0x20534444)的 DWORD (magic 数字)。

  • 文件中数据的说明。

    使用 DDS_HEADER; 通过标头说明来描述数据;像素格式是使用 DDS_PIXELFORMAT定义的。 请注意,DDS_HEADERDDS_PIXELFORMAT 结构取代了弃用的DDSURFACEDESC2、DDSCAPS2和 DDPIXELFORMAT DirectDraw 7 结构。 DDS_HEADER 是DDSURFACEDESC2和DDSCAPS2的二进制等效项。 DDS_PIXELFORMAT 是 DDPIXELFORMAT 的二进制等效项。

    DWORD               dwMagic;
    DDS_HEADER          header;
    
    

    如果将 DDS_PIXELFORMAT dwFlags 设置为 DDPF_FOURCC,dwFourCC 设置为“DX10”,则会出现额外的 DDS_HEADER_DXT10 结构,以适应无法表示为 RGB 像素格式(如浮点格式、sRGB 格式等)的纹理数组或 DXGI 格式。当 DDS_HEADER_DXT10 结构呈现时,整个数据说明将如下所示。

    DWORD               dwMagic;
    DDS_HEADER          header;
    DDS_HEADER_DXT10    header10;
    
  • 指向包含主图面数据的字节数组的指针。

    BYTE bdata[]
    
  • 指向包含剩余图面的字节数组的指针,例如:mipmap 级别、多维数据集地图中的人脸、卷纹理中的深度。 请按照以下链接了解有关 a:纹理多维数据集地图卷纹理的详细信息。

    BYTE bdata2[]
    

对于广泛的硬件支持,我们建议使用 DXGI_FORMAT_R8G8B8A8_UNORMDXGI_FORMAT_R8G8B8A8_UNORM_SRGBDXGI_FORMAT_R8G8B8A8_SNORMDXGI_FORMAT_B8G8R8A8_UNORMDXGI_FORMAT_R16G16_SNORMDXGI_FORMAT_R8G8_SNORMDXGI_FORMAT_R8_UNORMDXGI_FORMAT_BC1_UNORMDXGI_FORMAT_BC1_UNORM_SRGBDXGI_FORMAT_BC2_UNORMDXGI_FORMAT_BC2_UNORM_SRGBDXGI_FORMAT_BC3_UNORMDXGI_FORMAT_BC3_UNORM_SRGB 格式。

有关压缩纹理格式的详细信息,请参阅 Direct3D 11 中的 纹理块压缩和 块压缩(Direct3D 10)

D3DX 库(例如,D3DX11.lib)和其他类似库在 dwPitchOrLinearSize DDS_HEADER 结构的成员中提供音调值。< 因此,当你读取和写入 DDS 文件时,我们建议你以下列方式之一计算音调,以指示的格式之一:

  • 对于块压缩格式,将音调计算为:

    max( 1, (宽度+3)/4) * 块大小

    对于 DXT1、BC1 和 BC4 格式,块大小为 8 字节,对于其他块压缩格式,块大小为 16 字节。

  • 对于R8G8_B8G8、G8R8_G8B8、旧版 UYVY 打包格式和旧版 YUY2 打包格式,将音调计算为:

    (宽度+1) >> 1) * 4

  • 对于其他格式,将音调计算为:

    (宽度 * 每像素位 + 7 ) / 8

    将字节对齐除以 8。

注意

您计算的音调值并不总是等于运行时提供的音调,在某些情况下是 DWORD 对齐的,在其他情况下与字节对齐。 因此,我们建议一次复制扫描行,而不是尝试在一个副本中复制整个映像。

DDS 变体

有许多工具可以创建和使用 DDS 文件,但它们在标头中所需的详细信息可能有所不同。 编写器应尽可能完全填充标头,并且读取器应检查最小值以实现最大兼容性。 若要验证 DDS 文件,读取器应确保文件长度至少为 128 字节,以适应 magic 值和基本标头,magic 值0x20534444(“DDS”),DDS_HEADER大小为 124,标头大小中的DDS_PIXELFORMAT为 32。 如果DDS_PIXELFORMAT dwFlags 设置为 DDPF_FOURCC,dwFourCC 设置为“DX10”,则总文件大小至少为 148 字节。

在将像素格式设置为 dwFourCC 设置为D3DFORMAT或DXGI_FORMAT枚举值的DDPF_FOURCC代码时,可以使用一些常见变体。 无法判断枚举值是D3DFORMAT还是DXGI_FORMAT,因此强烈建议使用“DX10”扩展和DDS_HEADER_DXT10标头来存储 dxgiFormat(当基本DDS_PIXELFORMAT无法表达格式时)。

应首选标准DDS_PIXELFORMAT,以实现最大兼容性,以存储 RGB 未压缩的数据和 DXT1-5 数据,因为并非所有 DDS 工具都支持 DX10 扩展。

在 Direct3D 10/11 中使用纹理数组

Direct3D 10/11 中的新 DDS 结构(DDS_HEADERDDS_HEADER_DXT10)扩展了 DDS 文件格式以支持纹理数组,这是 Direct3D 10/11 中的新资源类型。 下面是一些示例代码,演示如何使用新标头访问纹理数组中的不同 mipmap 级别。

DWORD               dwMagic;
DDS_HEADER          header;
DDS_HEADER_DXT10    header10;
   
for (int iArrayElement = 0; iArrayElement < header10.arraySize; iArrayElement++)
{
   for (int iMipLevel = 0; iMipLevel < header.dwMipMapCount; iMipLevel++)
   {
     ...
   }
}       

常见的 DDS 文件资源格式和关联的标头内容

资源格式 dwFlags dwRGBBitCount dwRBitMask dwGBitMask dwBBitMask dwABitMask
DXGI_FORMAT_R8G8B8A8_UNORM
D3DFMT_A8B8G8R8
DDS_RGBA 32 0xff 0xff00 0xff0000 0xff000000
DXGI_FORMAT_R16G16_UNORM
D3DFMT_G16R16
DDS_RGBA 32 0xffff 0xffff0000
**
DXGI_FORMAT_R10G10B10A2_UNORM
D3DFMT_A2B10G10R10
DDS_RGBA 32 0x3ff 0xffc00 0x3ff00000
DXGI_FORMAT_R16G16_UNORM
D3DFMT_G16R16
DDS_RGB 32 0xffff 0xffff0000
DXGI_FORMAT_B5G5R5A1_UNORM
D3DFMT_A1R5G5B5
DDS_RGBA 16 0x7c00 0x3e0 0x1f 0x8000
DXGI_FORMAT_B5G6R5_UNORM
D3FMT_R5G6B5
DDS_RGB 16 0xf800 0x7e0 0x1f
DXGI_A8_UNORM
D3DFMT_A8
DDS_ALPHA 8 0xff
D3DFMT_A8R8G8B8
DDS_RGBA 32 0xff0000 0xff00 0xff 0xff000000
D3DFMT_X8R8G8B8
DDS_RGB 32 0xff0000 0xff00 0xff
D3DFMT_X8B8G8R8
DDS_RGB 32 0xff 0xff00 0xff0000
**
D3DFMT_A2R10G10B10
DDS_RGBA 32 0x3ff00000 0xffc00 0x3ff 0xc0000000
D3DFMT_R8G8B8
DDS_RGB 24 0xff0000 0xff00 0xff
D3DFMT_X1R5G5B5
DDS_RGB 16 0x7c00 0x3e0 0x1f
D3DFMT_A4R4G4B4
DDS_RGBA 16 0xf00 0xf0 0xf 0xf000
D3DFMT_X4R4G4B4
DDS_RGB 16 0xf00 0xf0 0xf
D3DFMT_A8R3G3B2
DDS_RGBA 16 0xe0 0x1c 0x3 0xff00
D3DFMT_A8L8
DDS_LUMINANCE 16 0xff 0xff00
D3DFMT_L16
DDS_LUMINANCE 16 0xffff
D3DFMT_L8
DDS_LUMINANCE 8 0xff
D3DFMT_A4L4
DDS_LUMINANCE 8 0xf 0xf0
资源格式 dwFlags dwFourCC
DXGI_FORMAT_BC1_UNORM
D3DFMT_DXT1
DDS_FOURCC “DXT1”
DXGI_FORMAT_BC2_UNORM
D3DFMT_DXT3
DDS_FOURCC “DXT3”
DXGI_FORMAT_BC3_UNORM
D3DFMT_DXT5
DDS_FOURCC “DXT5”
*
DXGI_FORMAT_BC4_UNORM
DDS_FOURCC “BC4U”
*
DXGI_FORMAT_BC4_SNORM
DDS_FOURCC “BC4S”
*
DXGI_FORMAT_BC5_UNORM
DDS_FOURCC “ATI2”
*
DXGI_FORMAT_BC5_SNORM
DDS_FOURCC “BC5S”
DXGI_FORMAT_R8G8_B8G8_UNORM
D3DFMT_R8G8_B8G8
DDS_FOURCC “RGBG”
DXGI_FORMAT_G8R8_G8B8_UNORM
D3DFMT_G8R8_G8B8
DDS_FOURCC “GRGB”
*
DXGI_FORMAT_R16G16B16A16_UNORM
D3DFMT_A16B16G16R16
DDS_FOURCC 36
*
DXGI_FORMAT_R16G16B16A16_SNORM
D3DFMT_Q16W16V16U16
DDS_FOURCC 110
*
DXGI_FORMAT_R16_FLOAT
D3DFMT_R16F
DDS_FOURCC 111
*
DXGI_FORMAT_R16G16_FLOAT
D3DFMT_G16R16F
DDS_FOURCC 112
*
DXGI_FORMAT_R16G16B16A16_FLOAT
D3DFMT_A16B16G16R16F
DDS_FOURCC 113
*
DXGI_FORMAT_R32_FLOAT
D3DFMT_R32F
DDS_FOURCC 114
*
DXGI_FORMAT_R32G32_FLOAT
D3DFMT_G32R32F
DDS_FOURCC 115
*
DXGI_FORMAT_R32G32B32A32_FLOAT
D3DFMT_A32B32G32R32F
DDS_FOURCC 116
D3DFMT_DXT2
DDS_FOURCC “DXT2”
D3DFMT_DXT4
DDS_FOURCC “DXT4”
D3DFMT_UYVY
DDS_FOURCC “UYVY”
D3DFMT_YUY2
DDS_FOURCC “YUY2”
D3DFMT_CxV8U8
DDS_FOURCC 117
任何 DXGI 格式 DDS_FOURCC “DX10”

* = 可靠的 DDS 读取器必须能够处理这些旧格式代码。 但是,当此类 DDS 读取器写入这些格式代码以避免歧义时,应首选使用“DX10”标头扩展。

** = 由于 DDS 读取器和编写器常见实现中存在一些长期问题,因此写出 10:10:10:2 类型的数据的最可靠方法是将“DX10”标头扩展与 DXGI_FORMAT 代码“24”(即DXGI_FORMAT_R10G10B10A2_UNORM值)一起使用。 D3DFMT_A2R10G10B10数据应转换为 10:10:10:2 类型的数据,然后再作为DXGI_FORMAT_R10G10B10A2_UNORM格式 DDS 文件写出。

DDS