c++ - 采样 D3D11 深度缓冲区时出现问题

标签 c++ directx directx-11 hlsl depth-buffer

我正在为延迟渲染管道准备好我的一个小型 DirectX 11.0 项目中的一切。但是,我在从像素着色器中对深度缓冲区进行采样时遇到了很多麻烦。

首先我定义深度纹理及其着色器资源 View :

    D3D11_TEXTURE2D_DESC depthTexDesc;
    ZeroMemory(&depthTexDesc, sizeof(depthTexDesc));
    depthTexDesc.Width = nWidth;
    depthTexDesc.Height = nHeight;
    depthTexDesc.Format = DXGI_FORMAT_R32_TYPELESS;
    depthTexDesc.Usage = D3D11_USAGE_DEFAULT;
    depthTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
    depthTexDesc.MipLevels = 1;
    depthTexDesc.ArraySize = 1;
    depthTexDesc.SampleDesc.Count = 1;
    depthTexDesc.SampleDesc.Quality = 0;
    depthTexDesc.CPUAccessFlags = 0;
    depthTexDesc.MiscFlags = 0;

    hresult = d3dDevice_->CreateTexture2D(&depthTexDesc, nullptr, &depthTexture_);

    D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc;
    ZeroMemory(&DSVDesc, sizeof(DSVDesc));
    DSVDesc.Format = DXGI_FORMAT_D32_FLOAT;
    DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    DSVDesc.Texture2D.MipSlice = 0;

    hresult = d3dDevice_->CreateDepthStencilView(depthTexture_, &DSVDesc, &depthView_);

    D3D11_SHADER_RESOURCE_VIEW_DESC gbDepthTexDesc;
    ZeroMemory(&gbDepthTexDesc, sizeof(gbDepthTexDesc));
    gbDepthTexDesc.Format = DXGI_FORMAT_R32_FLOAT;
    gbDepthTexDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    gbDepthTexDesc.Texture2D.MipLevels = 1;
    gbDepthTexDesc.Texture2D.MostDetailedMip = -1;

    d3dDevice_->CreateShaderResourceView(depthTexture_, &gbDepthTexDesc, &gbDepthView_);

这是我的渲染函数的相关部分:

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
    d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);
    d3dContext_->ClearDepthStencilView(depthView_, D3D11_CLEAR_DEPTH, 1.0f, 0);

    // GBuffer packing pass (in the future): /////////////////////////////////////////

    d3dContext_->OMSetRenderTargets(1, &backBufferTarget_, depthView_);

    unsigned int nStride = sizeof(Vertex);
    unsigned int nOffset = 0;

    d3dContext_->IASetInputLayout(inputLayout_);
    d3dContext_->IASetVertexBuffers(0, 1, &vertexBuffer_, &nStride, &nOffset);
    d3dContext_->IASetIndexBuffer(indexBuffer_, DXGI_FORMAT_R32_UINT, 0);
    d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    d3dContext_->VSSetShader(firstVS_, 0, 0);
    d3dContext_->PSSetShader(firstPS_, 0, 0);

    d3dContext_->DrawIndexed(nIndexCount_, 0, 0);

    d3dContext_->OMSetRenderTargets(1, &backBufferTarget_, nullptr);

    d3dContext_->VSSetShader(secondVS_, 0, 0);
    d3dContext_->PSSetShader(secondPS_, 0, 0);
    d3dContext_->PSGetShaderResources(0, 1, &gbDepthView_);
    d3dContext_->PSSetSamplers(0, 1, &colorMapSampler_);

    d3dContext_->DrawIndexed(nIndexCount_, 0, 0);

    swapChain_->Present(0, 0);

在这个临时实现中,firstVS_ 和 secondVS_ 是相同的,它们的唯一功能是进行所有转换并将数据传递给 PS。

最后,这里是 firstPS_ 和 secondPS_:

// firstPS_
float4 main(PS_Input frag) : SV_TARGET
{
    return float4(1.0f, 1.0f, 1.0f, 1.0f);
}

// secondPS_
Texture2D<float> depthMap_ : register(t0);
SamplerState colorSampler_ : register(s0);

float4 main(PS_Input frag) : SV_TARGET
{
    float4 psOut;
    psOut.xyz = depthMap_.Sample(colorSampler_, frag.tex0).xxx;
    psOut.w = 1.0f;
    return psOut;
}

所以,我的实际问题:

1) 所有这些代码编译都没有任何问题,但是当我对深度缓冲区进行采样时,它只是变黑了。我读到这可能是由于在您想要对深度缓冲区进行采样时,您的深度和模板 View 被 D3D11DeviceContext::OMSetRenderTargets() 绑定(bind)所致。我修好了,但缓冲区仍然是黑色的。我检查了图形调试器,但没有成功。那么,是我的深度缓冲区没有正确写入,还是我以错误的方式采样? firstPS_ 工作正常。

2) 说到采样,我正在使用的书上只说“我们将使用点采样器”,但我不知 Prop 体是什么意思。现在我只是在使用标准的纹理贴图采样器,但还有什么我应该用来采样的吗?

3) 此外,本书在 secondPS_ 中使用了 SamplerState.Gather() 函数,但当我尝试使用它时,它会提示“表达式无法映射到像素着色器指令集”。 Gather() 是书中的错误,还是我的 GPU(D3D 功能级别 11.0)不明白那是什么? Sample() 是否足以满足我的需求? Gather() 的最初用途是在深度缓冲区中围绕对象创建轮廓。

4) 我试图让 secondVS_ 只画一个全屏四边形,但 FXC 提示我对 SV_VertexID 的使用是“无效的”,说我的类型应该是完整的,即使它已经是。我在某处读到 SV_VertexID 只能由管道中的第一个 VS 使用。是这里的问题吗?在这种特殊情况下我该如何解决这个问题?在我目前低效的解决方案中,问题是由 UV 引起的吗?

最佳答案

1) 您调用了 PSGetShaderResources 而不是 PSSetShaderResources。此外,MostDetailedMip 应为 0 而不是 -1。

2) “点采样器”只是一个纹理采样器,其 FILTER 字段设置为 D3D11_FILTER_MIN_MAG_MIP_POINT 之类的东西。

3) Gather 是 Texture2D 上的一个函数,而不是您所说的 SamplerState。

4) 如果你使用 vs_4_0 编译你会得到这个错误,试试 vs_5_0。

关于c++ - 采样 D3D11 深度缓冲区时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32701729/

相关文章:

c++ - 从 VS2008 运行可执行文件崩溃并出现错误 "Application was unable to start correctly (0x000007b)"x64

c++ - 专门的模板类循环依赖

c++ - DirectX 着色器无法正常工作?

c++ - DirectX 11 : Runtime Assertion Failure using XMLoadFloat4X4()

c++ - 无效打印功能出错

c++ - 将 std::vector 传递给数组引用

c++ - DirectX 9 HLSL 与 DirectX 10 HLSL : syntax the same?

c++ - 在四叉树高度图地形上查找鼠标世界坐标 (3D)

c++ - DirectX 11 移动我的广场

c++ - DirectX 11 : Null Swap Chain