c++ - D3D11 : Rendering (depth) to texture results in red square, 正常渲染工作

标签 c++ directx-11 direct3d

我目前正在做一个 D3D 项目,想要实现定向阴影贴图。我根据 Microsoft Guide 设置了所有内容, 但它根本不起作用。

我已经创建了一个 2D 纹理对象、一个深度模板 View 和一个着色器资源 View ,并使用以下描述设置它们:

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

在这些步骤之间有额外的错误检查,但所有创建函数都成功返回。然后我绑定(bind)纹理,渲染我的场景并使用以下函数取消绑定(bind)纹理:

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

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

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

  • 所有 FAILED(hr) 调用都返回 false,没有错误消息打印到控制台
  • 我通过将几何体及其深度值 (z/w) 渲染到屏幕来测试几何体是否得到了正确的转换,效果和看起来都正确
  • 我测试了在片段着色器中计算深度值并渲染到普通渲染目标(基本上是尝试将我的颜色缓冲区渲染到纹理)而不是深度模板纹理,但这也不起作用,红色方 block <
  • 我为阴影贴图和 View 测试了不同的格式和格式组合,这导致创建失败或没有改变任何东西
  • 我检查了在渲染调用期间将我的纹理设置为渲染目标和取消设置之间的任何调用是否将深度模板目标重置为其他目标 - 不是这种情况
  • 我已经调试了我的纹理到屏幕/四边形渲染例程,它可以与其他纹理一起正常工作,所以我实际上看到了深度纹理的样子
  • 我改变了周围的几何形状和相机视角,看看是否能在深度纹理中看到任何东西 - 它没有
  • 我遇到了 this similar StackOverflow problem并检查我的默认深度模板缓冲区是否具有与我的纹理相同的尺寸、AA 设置等 - 它确实如此(计数 1,质量 0)

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

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

提前致谢。

最佳答案

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

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

关于c++ - D3D11 : Rendering (depth) to texture results in red square, 正常渲染工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55633115/

相关文章:

c# - 使用 SlimDX 绘制 2D

C++ - 如何创建一个 vector ,其中每个元素都是来自输入字符串的单个数字?

c++ - 找不到 d3dx11.lib?

libmysql.dll 中的 C++ MySQL 错误

c++ - Directx 11 渲染问题,没有显示三角形

c++ - 由于 ID3D11Buffer 而导致访问冲突

xna - 3D 角色/模型创建者

c++ - Direct3d 中的 vector 文本渲染系统

c++ - 变量失去它的值(value)

c++ - 从命名管道读入时,char 数组会自动附加一个空终止符吗?