我试图以同样的方式为DX9和DX11生成mipmap,我需要它们从像素着色器中采样特定的级别。在那之后,我注意到在不同的DX版本上,抽样是不同的,而且在DX11中更糟,对DX9更好。
接下来,我尝试通过使用ImGui呈现一个备份副本图像并缩小4倍的大小来可视化它,结果如下:
带有mipmap生成的DX9:dx9 w mips
没有mipmap生成的DX9:dx9
带有mipmap生成的DX11:dx11 w mips
没有mipmap生成的DX11:dx11
纹理的创建是完全相同的:
DX9
static IDirect3DTexture9* pBackBufferResource = nullptr;
IDirect3DSurface9* pBackBuffer = nullptr;
g_pd3dDevice->GetBackBuffer(0U, 0U, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
D3DSURFACE_DESC descBack = { };
pBackBuffer->GetDesc(&descBack);
if (pBackBufferResource == nullptr)
{
g_pd3dDevice->CreateTexture(descBack.Width, descBack.Height, 1U, D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, descBack.Format, D3DPOOL_DEFAULT, &pBackBufferResource, nullptr);
/*
* explicitly set linear filter for mipmap generation
* for some reason 'D3DSAMP_MIPFILTER' sampler state doesn't actually change this
*/
pBackBufferResource->SetAutoGenFilterType(D3DTEXF_LINEAR);
}
// get the most detailed mip-level surface
IDirect3DSurface9* pResourceTopSurface = nullptr;
pBackBufferResource->GetSurfaceLevel(0U, &pResourceTopSurface);
// because backbuffer haven't mipmap, we couldn't just copy its texture, we're update only most detailed mip-level
g_pd3dDevice->StretchRect(pBackBuffer, nullptr, pResourceTopSurface, nullptr, D3DTEXF_LINEAR);
// the 'D3DUSAGE_AUTOGENMIPMAP' flag of texture creation will regenerate mipmap automatically, but here do it manually just for sure
pBackBufferResource->GenerateMipSubLevels();
ImVec2 vecMin = { 10.f, 10.f };
ImVec2 vecMax = { vecMin.x + floorf((float)descBack.Width / 4.0f), vecMin.y + floorf((float)descBack.Height / 4.0f) };
ImGui::GetForegroundDrawList()->AddImage(pBackBufferResource, vecMin, vecMax);
ImGui::GetForegroundDrawList()->AddRect(vecMin, vecMax, IM_COL32(0, 0, 0, 255));DX11
static ID3D11Texture2D* pBackBufferCopy = nullptr;
static ID3D11ShaderResourceView* pBackBufferResource = nullptr;
ID3D11Texture2D* pBackBuffer = nullptr;
g_mainRenderTargetView->GetResource(reinterpret_cast<ID3D11Resource**>(&pBackBuffer));
D3D11_TEXTURE2D_DESC descBack = { };
pBackBuffer->GetDesc(&descBack);
if (pBackBufferCopy == nullptr)
{
D3D11_TEXTURE2D_DESC descBackCopy = descBack;
descBackCopy.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
descBackCopy.MipLevels = 0U;
descBackCopy.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
g_pd3dDevice->CreateTexture2D(&descBackCopy, nullptr, &pBackBufferCopy);
}
// because backbuffer haven't mipmap, we couldn't copy its texture just with 'CopyResource()', so we're update only most detailed mip-level
g_pd3dDeviceContext->CopySubresourceRegion(pBackBufferCopy, 0U, 0U, 0U, 0U, pBackBuffer, 0U, nullptr);
pBackBuffer->Release();
if (pBackBufferResource == nullptr)
{
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDescBuffer = { };
resourceViewDescBuffer.Format = descBack.Format;
resourceViewDescBuffer.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resourceViewDescBuffer.Texture2D.MostDetailedMip = 0U;
resourceViewDescBuffer.Texture2D.MipLevels = ~0U;
g_pd3dDevice->CreateShaderResourceView(pBackBufferCopy, &resourceViewDescBuffer, &pBackBufferResource);
}
// regenerate mipmap based on updated most detailed mip-level
g_pd3dDeviceContext->GenerateMips(pBackBufferResource);
ImVec2 vecMin = { 10.f, 10.f };
ImVec2 vecMax = { vecMin.x + floorf((float)descBack.Width / 4.0f), vecMin.y + floorf((float)descBack.Height / 4.0f) };
ImGui::GetForegroundDrawList()->AddImage(pBackBufferResource, vecMin, vecMax);
ImGui::GetForegroundDrawList()->AddRect(vecMin, vecMax, IM_COL32(0, 0, 0, 255));MIN/MAG/MIP滤波器的采样状态为线性,MaxLOD为D3D11_FLOAT32_MAX。很明显,DX11图像过于锐利,看上去与w/o映射相同。所以我的问题是为什么它发生在DX11,而不是发生在DX9,当我确信它确实正确地生成mipmap,并且我可以从它们在着色器内采样(着色取样也看起来更清晰)?
发布于 2022-07-09 19:30:40
一般的答案是自动生成的mipmips完全由驱动程序决定。因此,自动生成的mips的质量因驱动程序的不同而有很大差异,在某些情况下,对于某些格式,它可以像点采样一样低质量。
这实际上是DirectX 12没有“自动生成的mips”功能的原因之一。相反,如果您需要此功能,建议使用计算机着色器。有关示例,请参见用于DirectX的DX12工具包。
尽管如此,您需要验证所有返回HRESULT值的函数,因为您可能会在忽略的某个地方得到一个错误代码。例如,我怀疑在交换链缓冲区上调用SetAutoGenFilterType是否真的像您认为的那样。即使您只是将它们视为快速失败,也不要忽略HRESULT返回。
对于DirectX 11,应该启用调试设备并查找输出。由于DirectX 9是遗留的,因此自Windows7以来就不支持用于它的“调试设备”。
https://stackoverflow.com/questions/72922067
复制相似问题