如何将压缩的 DDS 格式纹理与 mip 映射一起使用?

时间:2021-07-22 14:41:14

标签: c++ direct3d

直到现在,我将 D3D11_TEXTURE2D_DESC::MipLevels 设置为 1,但为了提高地形纹理的性能和质量,我尝试将其替换为带有 mipmap 的纹理。所以这是我用来使用 mipmap 创建纹理的代码:

 D3D11_TEXTURE2D_DESC t2d;
ZeroMemory(&t2d, sizeof(D3D11_TEXTURE2D_DESC));

UINT BindFlags = (D3D11_BIND_SHADER_RESOURCE | (m_Header.dwMipMapCount ? D3D11_BIND_RENDER_TARGET : 0)); // if the texture has mipmaps then bind it to render target.

t2d.Format = GetDXGIFormat(m_Header.ddspf); // BC2_UNORM
t2d.Width = m_Header.dwWidth;
t2d.Height = m_Header.dwHeight;
t2d.MipLevels = !m_Header.dwMipMapCount ? 1 : 0; // if the texture has mip maps then set it to 0 in order to use them all.
t2d.ArraySize = 1;
t2d.SampleDesc.Count = 1;
t2d.Usage = D3D11_USAGE_DEFAULT;
t2d.BindFlags = BindFlags;
if(!t2d.MipLevels) // only set if the texture has mip maps.
    t2d.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

D3D11_SUBRESOURCE_DATA sd;
ZeroMemory(&sd, sizeof(D3D11_SUBRESOURCE_DATA));

sd.pSysMem = m_DDSData;

switch (t2d.Format) {
case DXGI_FORMAT_BC1_UNORM:
    sd.SysMemPitch = 8 * (m_Header.dwWidth / 4);
    break;
case DXGI_FORMAT_BC2_UNORM:
case DXGI_FORMAT_BC3_UNORM:
    sd.SysMemPitch = 16 * (m_Header.dwWidth / 4);
    break;
case DXGI_FORMAT_R8G8B8A8_UNORM:
case DXGI_FORMAT_B8G8R8A8_UNORM:
    sd.SysMemPitch = m_Header.dwWidth * 4;
    break;
default:
    return Log("Unsupported texture format.");
}

hr = pDevice->CreateTexture2D(&t2d, &sd, &m_pTexture2D);
if (FAILED(hr))
    return Log("Failed to create texture.");

当我的代码运行并找到带有 mip 贴图的纹理时,它最终失败了,这是我在调试时收到的错误消息:

<块引用>

D3D11 错误:ID3D11Device::CreateTexture2D:格式(0x4a,BC2_UNORM)无法绑定为 RenderTarget,或转换为可以绑定为 RenderTarget 的格式。因此这种格式不支持 D3D11_BIND_RENDER_TARGET。 [ STATE_CREATION 错误 #92:CREATETEXTURE2D_UNSUPPORTEDFORMAT]

但是如果它找到没有 mip 贴图的纹理,或者甚至是带有 mip 贴图的纹理,但我将纹理描述上的 mip 贴图设置为 1,我不会收到错误消息。正如错误消息中所说,我无法将纹理绑定到渲染目标,但是如果我尝试使用 D3D11_RESOURCE_MISC_GENERATE_MIPS,我会收到一条错误消息,指出纹理需要绑定到 {{1} }.

1 个答案:

答案 0 :(得分:1)

自动生成 mipmap 不支持块压缩格式。您可以使用 CheckFormatSupport 确认这一点。

bool autogen = false;
UINT fmtSupport = 0;
hr = d3dDevice->CheckFormatSupport(format, &fmtSupport);
if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN))
{
    // 10level9 feature levels do not support auto-gen mipgen for volume textures
    if ((resDim != D3D11_RESOURCE_DIMENSION_TEXTURE3D)
        || (d3dDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0))
    {
        autogen = true;
    }
}

通常,您需要离线压缩纹理并生成 mipmap 作为该处理的一部分。这些可以存储在 DDS 文件中,然后在运行时与 mips 一起加载。

有关支持 mipmap 生成、块压缩和 DDS 编解码器的 C++ 库,请参阅 DirectXTex。它还包括 DDSTextureLoader 模块,这是一个轻量级的 DDS 文件加载器。

<块引用>

对于非常大的数据集,已经使用了替代方案,其中使用一些在运行时加载的有损格式(如 JPEG)压缩高分辨率图像,然后软件或基于 GPU 的盒式过滤器生成 mips。然后使用 Fast Block Compression 方案压缩该纹理的所有级别。它的质量不如离线压缩,但在某些情况下值得权衡。

<块引用>

请记住,块压缩格式具有固定的 2:1 或 4:1 压缩比,但优点是您无需解压缩它们,因为硬件可以直接使用它进行渲染。

相关问题