D3D11:渲染(深度)到纹理导致红色方块,正常渲染工作

D3D11: Rendering (depth) to texture results in red square, normal rendering works

我目前正在做一个 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_);

在这些步骤之间还有额外的错误检查,但所有创建函数 return 都成功了。然后我绑定纹理,渲染我的场景并使用以下函数解除绑定纹理:

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();

从光的角度将场景渲染到正常的渲染目标(屏幕)会产生正确的图像(包括实际图像和仅渲染深度值)。我使用一个简单的顶点着色器,它只转换顶点和一个像素着色器,它什么也不做,或者 returns 深度值(我都试过了,不会改变最终结果的任何东西,因为我们不关心关于颜色缓冲区)。

清除纹理并对其进行渲染后,我将其渲染到屏幕的四边形上,但我得到的只是一个红色方块 - 所以深度值为 1.0f,我已将纹理清除到的值.我真的不知道该怎么做,我尝试了一切,从在线教程中实施了所有可能的解决方案,或者自己改变了一些东西,但没有任何帮助。这是我已经检查过的所有内容的列表:

我真的不知道发生了什么,我已经尝试调试了好几个小时。我希望这里有人可以就我做错了什么或者我可以尝试解决这个问题给我任何建议。我将 C++11 与 Direct3D11 结合使用。

注意:我无法使用 NSight 或任何 Visual Studio 工具调试任何这些,因为它们现在似乎无法在我的系统上正常工作,而且我没有任何管理权限来修复任何一个。我现在只需要处理它。我希望给定的信息和代码示例足以让我大致了解我还可以尝试使这项工作成为可能。

提前致谢。

我让 NSight 工作并用它调试了整个过程。事实证明深度纹理已正确创建并填充了深度和模板数据,我只是忘记了所有深度信息都存储在第一个通道中 - 所以我忽略了 g 和 b 数据并将 1.0 用于 a 并且它起作用了。使用 g 和 b 通道以某种方式使整个事物变红(也许有人想对此进行补充并解释原因)。

一旦我可以观察到着色器中存在的纹理,调试就会变得容易得多 - 我应该早点使用像 NSight 或 RenderDoc 这样的调试工具。感谢@EgorShkorov 的建议。