最近我遇到了在d3d11中为立方体贴图创建mipmap的问题。让DirectX框架为立方体贴图中的每个平面生成每个lod的图像的想法,但似乎我应该为它们手动创建。
为纹理生成mips的正确方法是什么?我必须自己生成它们,还是有办法让d3d来做它们?
这就是我创建纹理的方式:
void TextureCube::Initialize(Renderer & device, CubemapRef cubemap)
{
HRESULT result;
BitmapRef bitmap = cubemap->GetPosX(); //assume that everything is equal there
int ch = bitmap->GetCh();
DXGI_FORMAT fmt = bitmapformats[ch % 4];
m_format = fmt;
m_w = cubemap->GetPosX()->GetX();
m_h = cubemap->GetPosX()->GetY();
m_ch = (m_ch == 3) ? 4 : ch; // if bitmap has 3 component per pixel, we'll force it to 4 and convert it before creating initial data
m_chW = 1;
D3D11_TEXTURE2D_DESC textureDesc;
ZeroMemory(&textureDesc, sizeof(textureDesc));
textureDesc.Width = m_w;
textureDesc.Height = m_h;
textureDesc.MipLevels = 0;
textureDesc.ArraySize = 6;
textureDesc.Format = m_format;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE| D3D11_BIND_RENDER_TARGET;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | D3D11_RESOURCE_MISC_GENERATE_MIPS;
// --- setup inital data
D3D11_SUBRESOURCE_DATA pData[6];
for (int i = 0; i < 6; i++)
{
void *inData = cubemap->GetBitmap(i)->GetData();
void *outData = inData;
if (cubemap->GetBitmap(i)->GetCh() == 3) {
outData = new unsigned int[m_w * m_h];
CopyChannel3To4(inData, outData, m_w, m_h);
}
pData[i].pSysMem = outData;
pData[i].SysMemPitch = m_w * 4;
pData[i].SysMemSlicePitch = 0;
}
ID3D11Texture2D *ppTex = nullptr;
result = device->CreateTexture2D(&textureDesc, pData, &ppTex);
// cleanup converted data
for (int i = 0; i < 6; i++)
if (pData[i].pSysMem != cubemap->GetBitmap(i)->GetData())
delete pData[i].pSysMem;
if (FAILED(result))
throw EX_HRESULT(TextureCreateException, result);
m_pTexture = ppTex;
// --- srv
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
shaderResourceViewDesc.Format = m_format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
shaderResourceViewDesc.TextureCube.MipLevels = -1;
result = device->CreateShaderResourceView(m_pTexture, &shaderResourceViewDesc, &m_pResourceView);
if (FAILED(result))
throw EX_HRESULT(TextureCreateException, result);
}