C++ D3D11:渲染(深度)到纹理会产生红方块,正常渲染有效
我目前正在从事一个D3D项目,希望实现方向阴影映射。我按照计划把一切都安排好了,但就是不起作用 我已经创建了2D纹理对象、深度模具视图和着色器资源视图,并使用以下描述进行了设置:C++ D3D11:渲染(深度)到纹理会产生红方块,正常渲染有效,c++,directx-11,direct3d,C++,Directx 11,Direct3d,我目前正在从事一个D3D项目,希望实现方向阴影映射。我按照计划把一切都安排好了,但就是不起作用 我已经创建了2D纹理对象、深度模具视图和着色器资源视图,并使用以下描述进行了设置: D3D11_TEXTURE2D_DESC shadowMapDesc; ZeroMemory(&shadowMapDesc, sizeof(D3D11_TEXTURE2D_DESC)); shadowMapDesc.Width = width; shadowMapDesc.Hei
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函数都会成功返回。然后使用以下函数绑定纹理、渲染场景并解除绑定纹理:
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);
}
将场景从灯光透视渲染到正常渲染目标(屏幕)将生成正确的图像(实际图像和仅渲染深度值)。我使用了一个简单的顶点着色器,它只变换顶点,而像素着色器则什么都不做或返回深度值(我尝试了这两种方法,因为我们不关心颜色缓冲区,所以不会改变最终结果)
清除纹理并对其进行渲染后,我将其渲染到屏幕的四边形上,但我得到的只是一个红方块-因此深度值为1.0f,即我已清除纹理的值。我真的不知道该怎么办,我尝试了所有的方法,从在线教程中实现了所有可能的解决方案,或者自己改变了一些事情,但没有任何帮助。以下是我已经检查过的所有内容的列表:
- 所有失败(hr)-呼叫返回false,没有错误消息打印到控制台
- 我通过将几何体及其深度值(z/w)渲染到屏幕上,测试了几何体是否正确地进行了变换,该操作有效且看起来正确
- 我测试了在片段着色器中计算深度值,并将其渲染到普通渲染目标(基本上是尝试将颜色缓冲区渲染到纹理),而不是深度模具纹理,但这也不起作用,红方块
- 我测试了阴影贴图和视图的不同格式和格式组合,这要么导致创建失败,要么没有改变任何东西
- 我检查了在渲染调用期间设置和取消设置我的纹理作为渲染目标之间的任何调用是否将深度模具目标重置为其他对象-情况并非如此
- 我已经调试了我的纹理到屏幕/四边形渲染例程,它可以与其他纹理正常工作,所以我实际上看到了深度纹理的样子
- 我改变了周围的几何体和相机透视图,看看这是否会使深度纹理中的任何东西可见-它不会
- 我偶然发现并检查了我的默认深度模具缓冲区是否与我的纹理具有相同的尺寸、AA设置等,并且确实如此(计数1,质量0)
提前谢谢。我马上开始工作,并用它调试了整个过程。事实证明,深度纹理是正确创建的,并填充了深度和模具数据,而我只是忘记了所有深度信息都存储在第一个通道中-因此我忽略了g和b数据,并使用1.0表示a,结果成功了。使用g和b频道不知何故使整个事情变得红色(也许有人想添加到这一点并解释原因)
一旦我能观察到着色器中存在的纹理,调试就变得容易多了——我早就应该使用NSight或RenderDoc之类的调试工具了。感谢@EgorShkorov的建议。您是否尝试过使用RenderDoc检查真正提交给API的内容?它有像素的历史和所有的酷东西的DX11。我认为它有一个可移植的版本,所以你不必授予管理权限。如果你可以在这里捕获并共享它,回答你的问题将非常有帮助。捕获是从应用程序捕获帧后保存的.rdc文件。以下是生成的链接:,您需要最新的可移植生成。解压它并遵循文档:我将检查它并在下周一报告,谢谢!
camera = buildCameraFromLight(light);
setCameraCBuffer(camera);
bindTexture();
activateShader();
for(Object j : objects) {setTransformationCBuffer(j); renderObject(j);}
deactivateShader();
unbindTexture();