dds文件头必须用#pragma pack(1)强制1字节对齐,硬编码读取124字节,校验dwsize==124和dwmagic==0x20534444;dxt格式由ddspf.dwfourcc决定,需按makefourcc映射dxgi_format;宽高须向上对齐到4计算块尺寸,mipmap各级数据连续存储且尺寸逐级减半。

DDS 文件头结构怎么解析才不会错字节对齐
DDS 文件头固定为 124 字节,但直接 fread 124 字节进结构体极易出错——关键在于 Windows SDK 中的 DDS_HEADER 结构默认按 4 字节对齐,而实际文件是紧凑排列(no padding)。若用 C++ 结构体未显式指定对齐,编译器可能插入填充字节,导致 dwWidth、dwHeight 等字段读错。
- 必须用
#pragma pack(1)或__attribute__((packed))(GCC/Clang)强制 1 字节对齐 - 不要依赖
sizeof(DDS_HEADER)判断读取长度;硬编码 124 更安全 - 读完后务必检查
dwSize == 124和dwMagic == 0x20534444(即 "DDS " ASCII 反序) -
dwFlags需按位与DDSD_WIDTH/DDSD_HEIGHT/DDSD_PIXELFORMAT等宏判断哪些字段有效
如何正确识别 DXT 压缩格式并映射到 DXGI_FORMAT
DDS 中压缩纹理类型藏在 ddspf.dwFourCC,不是靠扩展名或猜测。常见值如 DXT1、DXT5 对应不同通道支持和 alpha 处理逻辑,直接映射错误会导致解压花屏或 alpha 丢失。
-
dwFourCC == MAKEFOURCC('D','X','T','1')→DXGI_FORMAT_BC1_UNORM(无 alpha)或DXGI_FORMAT_BC1_UNORM_SRGB(sRGB) -
dwFourCC == MAKEFOURCC('D','X','T','5')→DXGI_FORMAT_BC3_UNORM(有 alpha);注意 DXT3 和 DXT5 的 alpha 编码方式不同,不能混用 -
dwFourCC == MAKEFOURCC('B','C','4','U')或'B','C','4','S'→ 分别对应无符号/有符号单通道,常用于法线贴图 - 若
ddspf.dwFlags & DDPF_FOURCC == 0,说明是 RGB(A) 未压缩格式,此时看ddspf.dwRGBBitCount和掩码字段
读取 DXT 块数据时为什么宽高要向上对齐到 4
DXT 压缩以 4×4 像素块为单位,每个块固定占若干字节(如 DXT1 是 8 字节,DXT5 是 16 字节)。因此真实数据宽度和高度必须按 4 向上取整,否则 memcpy 会越界或漏块。
- 计算块宽:
blockWidth = (width + 3) / 4,块高同理 - 单块字节数由
dwFourCC决定:查 MSDN 文档或用 switch 映射,例如BC1 → 8,BC3 → 16 - 总压缩数据大小 =
blockWidth * blockHeight * bytesPerBlock,不是width * height * bytesPerPixel - 若文件中
dwPitchOrLinearSize非零,优先用它(尤其对非幂等尺寸),但需验证是否匹配上述计算值
加载多级 mipmap 时容易忽略的链式结构
DDS 支持多级 mipmap 连续存储在文件头之后,但并非每级都带完整头信息——只有第一级有 DDS_HEADER,后续各级仅存原始压缩块数据,尺寸逐级减半(向下取整,最小为 1)。
- 通过
dwMipMapCount > 1判断是否存在 mipmap;若为 0,需手动设为 1(表示只有 base level) - 每级尺寸:从
dwWidth/dwHeight开始,每次max(1, size >> 1),不可简单除 2 后截断 - 各级数据偏移 = 上一级偏移 + 上一级压缩数据大小;必须累加计算,不能假设等距
- OpenGL 或 Vulkan 加载时,需对每级调用一次
glCompressedTexImage2D或vkCmdCopyBufferToImage,传入对应尺寸和数据指针
最易被跳过的点:DXT 格式不支持任意尺寸,width % 4 != 0 或 height % 4 != 0 时,文件本身已按块对齐补零——这些 padding 像素属于有效数据流,必须原样保留并传给 GPU,不能裁剪。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











