D3D11:渲染(深度)到纹理结果为红色正方形,正常渲染工作

问题描述 投票:1回答:1

我目前正在研究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,我清除了纹理的值。我真的不知所措,我尝试了一切,从在线教程中实现了所有可能的解决方案,或者我自己改变了一些东西,但没有任何帮助。这是我已经检查过的所有内容的列表:

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

我真的不知道是什么,我一直试图调试这几个小时。我希望这里有人可以就我做错了什么或者我可以尝试解决这个问题给出任何建议。我正在使用带有Direct3D11的C ++ 11。

注意:我无法使用NSight或任何Visual Studio工具调试任何此类工具,因为它们现在似乎无法正常使用我的系统,并且我没有任何管理权限来修复任何这些工具。我现在只需处理它。我希望给定的信息和代码示例足以提供我可以尝试使其工作的粗略概念。

提前致谢。

c++ directx-11 direct3d
1个回答
1
投票

我让NSight工作并调试了整个事情。结果是深度纹理被正确创建并填充了深度和模板数据,我忘了所有的深度信息都存储在第一个通道中 - 所以我忽略了g和b数据并使用了1.0作为a并且它起作用了。使用g和b通道以某种方式使整个事情变得红色(也许有人想要添加到此并解释原因)。

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

© www.soinside.com 2019 - 2024. All rights reserved.