DirectX 11创建1bpp单色2D纹理:DXGI_FORMAT_R1_UNORM不支持求替代格式
DXGI_FORMAT_R1_UNORM格式不支持的问题 我完全懂你现在的困扰——想创建1bpp的单色纹理,选了DXGI_FORMAT_R1_UNORM却碰了壁,设备直接抛出不支持的错误。别慌,咱们来拆解问题,找个靠谱的替代方案。
首先得明确:DXGI_FORMAT_R1_UNORM是DirectX 12才引入的格式,DirectX 11的硬件和API本身就不支持它,这就是你看到CREATETEXTURE2D_UNSUPPORTEDFORMAT错误的核心原因。
推荐的替代格式及处理方案
根据你的需求(单色1bpp纹理用于渲染),有几个兼容性拉满的选项,按易用性排序:
1. DXGI_FORMAT_R8_UNORM 或 DXGI_FORMAT_A8_UNORM
这两个都是DirectX 11全平台支持的8bpp格式,处理起来最简单。你只需要把打包的1位像素数据,转换成每个像素占1字节的格式(0x00代表黑色,0xFF代表白色)。
另外注意你代码里的一个小bug:D3D11_USAGE_DEFAULT和D3D11_CPU_ACCESS_WRITE是冲突的——DEFAULT类型的资源CPU无法直接写入,如果你只是初始化时写入纹理,直接去掉CPUAccessFlags即可;如果后续需要CPU更新,要把Usage改成D3D11_USAGE_DYNAMIC。
修正后的示例代码(以DXGI_FORMAT_R8_UNORM为例):
D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = 32; desc.Height = 32; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R8_UNORM; // 替换为支持的格式 desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; // DEFAULT用法不需要CPU写权限 desc.MipLevels = 1; desc.SampleDesc.Count = 1; desc.MiscFlags = 0; // 将1bpp的bitmapPixels转换为R8_UNORM格式:每个位转为1字节 std::vector<BYTE> convertedPixels(32 * 32); for (int y = 0; y < 32; y++) { for (int x = 0; x < 32; x++) { int byteIndex = y * 4 + x / 8; // 原数据每行4字节(32位) int bitIndex = 7 - (x % 8); // 从高位到低位取bit bool isWhite = (bitmapPixels[byteIndex] >> bitIndex) & 1; convertedPixels[y * 32 + x] = isWhite ? 0xFF : 0x00; } } const D3D11_SUBRESOURCE_DATA subResourceData = { convertedPixels.data(), 32, // 每行字节数(32像素×1字节) 32 * 32 // 总字节数 }; device->CreateTexture2D(&desc, &subResourceData, &texture2D);
2. DXGI_FORMAT_BC4_UNORM(块压缩格式)
如果你的纹理尺寸较大,想节省显存,可以用BC4压缩格式(每个4×4块占8字节,等效于1bpp)。不过这个需要把你的1bpp数据打包成BC4的块结构,处理逻辑会复杂一些,适合对显存占用有要求的场景。
总结
优先选DXGI_FORMAT_R8_UNORM或DXGI_FORMAT_A8_UNORM,兼容性好且处理简单;如果追求显存效率再考虑BC4格式。同时一定要修正Usage和CPUAccessFlags的冲突问题,避免额外的创建错误。
内容的提问来源于stack exchange,提问作者Tajuddin Khandaker

