我目前正在研究D3D项目,并希望实现定向阴影映射。我根据Microsoft Guide设置了一切,但它不起作用。
我创建了一个2D纹理对象,一个深度模板视图和一个着色器资源视图,并使用以下描述进行设置:
D3D11_TEXTURE2D_DESC shadowMapDesc;
ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC));
shadowMapDesc.Width = width;
shadowMapDesc.Height = height;
shadowMapDesc.MipLevels = 1;
shadowMapDesc.ArraySize = 1;
shadowMapDesc.Format = DXGI_FORMAT_R24G8_TYPELESS;
shadowMapDesc.SampleDesc.Count = 1;
shadowMapDesc.SampleDesc.Quality = 0;
shadowMapDesc.Usage = D3D11_USAGE_DEFAULT;
shadowMapDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
shadowMapDesc.CPUAccessFlags = 0;
shadowMapDesc.MiscFlags = 0;
ID3D11Device& d3ddev = dev.getD3DDevice();
uint32_t *initData = new uint32_t[width * height];
ZeroMemory(initData, sizeof(uint32_t) * width * height);
D3D11_SUBRESOURCE_DATA data;
ZeroMemory(&data, sizeof(D3D11_SUBRESOURCE_DATA));
data.pSysMem = initData;
data.SysMemPitch = sizeof(uint32_t) * width;
data.SysMemSlicePitch = 0;
HRESULT hr = d3ddev.CreateTexture2D(&shadowMapDesc, &data, &texture_);
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
ZeroMemory(&depthStencilViewDesc, sizeof(D3D11_DEPTH_STENCIL_VIEW_DESC));
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
hr = d3ddev.CreateDepthStencilView(texture_, &depthStencilViewDesc, &stencilView_);
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
ZeroMemory(&shaderResourceViewDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
hr = d3ddev.CreateShaderResourceView(texture_, &shaderResourceViewDesc, &shaderView_);
在这些步骤之间有额外的错误检查,但所有create-functions都成功返回。然后,我使用以下函数绑定纹理,渲染场景并解除纹理绑定:
void D3DDepthTexture2D::bindAsTarget(D3DDevice& dev)
{
dev.getDeviceContext().ClearDepthStencilView(stencilView_, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
// Bind target
dev.getDeviceContext().OMSetRenderTargets(0, 0, stencilView_);
// Set viewport
dev.setViewport(static_cast<float>(width_), static_cast<float>(height_), 0.0f, 0.0f);
}
void D3DDepthTexture2D::unbindAsTarget(D3DDevice& dev, float width, float height)
{
// Unbind target
dev.resetRenderTarget();
// Reset viewport
dev.setViewport(width, height, 0.0f, 0.0f);
}
我的渲染到深度纹理程序基本上看起来像这样(删除所有不必要的细节):
camera = buildCameraFromLight(light);
setCameraCBuffer(camera);
bindTexture();
activateShader();
for(Object j : objects) {setTransformationCBuffer(j); renderObject(j);}
deactivateShader();
unbindTexture();
将场景从灯光透视渲染到正常渲染目标(屏幕)会产生正确的图像(实际图像和仅渲染深度值)。我使用一个简单的顶点着色器,只是转换顶点和一个什么都不做的像素着色器或者返回深度值(我试过两个,不改变最终结果,因为我们不关心颜色缓冲区) 。
清除纹理并渲染到它后,我将它渲染到我的屏幕上的四边形,但我得到的只是一个红色方块 - 所以深度值是1.0f,我清除了纹理的值。我真的不知所措,我尝试了一切,从在线教程中实现了所有可能的解决方案,或者我自己改变了一些东西,但没有任何帮助。这是我已经检查过的所有内容的列表:
我真的不知道是什么,我一直试图调试这几个小时。我希望这里有人可以就我做错了什么或者我可以尝试解决这个问题给出任何建议。我正在使用带有Direct3D11的C ++ 11。
注意:我无法使用NSight或任何Visual Studio工具调试任何此类工具,因为它们现在似乎无法正常使用我的系统,并且我没有任何管理权限来修复任何这些工具。我现在只需处理它。我希望给定的信息和代码示例足以提供我可以尝试使其工作的粗略概念。
提前致谢。
我让NSight工作并调试了整个事情。结果是深度纹理被正确创建并填充了深度和模板数据,我忘了所有的深度信息都存储在第一个通道中 - 所以我忽略了g和b数据并使用了1.0作为a并且它起作用了。使用g和b通道以某种方式使整个事情变得红色(也许有人想要添加到此并解释原因)。
一旦我观察到着色器中存在的纹理,调试就变得容易了 - 我应该先使用像NSight或RenderDoc这样的调试工具。感谢@EgorShkorov的建议。