C++ 采样D3D11深度缓冲区时出现的问题

C++ 采样D3D11深度缓冲区时出现的问题,c++,directx,directx-11,hlsl,depth-buffer,C++,Directx,Directx 11,Hlsl,Depth Buffer,我正在我的一个DirectX 11.0小项目中为延迟渲染管道做好一切准备。但是,在从像素着色器中采样深度缓冲区时,我遇到了很多麻烦 首先,我定义深度纹理及其着色器资源视图: D3D11_TEXTURE2D_DESC depthTexDesc; ZeroMemory(&depthTexDesc, sizeof(depthTexDesc)); depthTexDesc.Width = nWidth; depthTexDesc.Height = nHeight;

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

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

    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_uu和secondVS_u是相同的,它们唯一的功能是执行所有转换并将数据传递给PSs

最后,这里是第一个p和第二个p:

// 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;
}
//firstPS_
浮动4主(PS_输入框架):SV_目标
{
返回浮动4(1.0f、1.0f、1.0f、1.0f);
}
//第二_
纹理2d深度映射:寄存器(t0);
采样器状态颜色采样器:寄存器(s0);
浮动4主(PS_输入框架):SV_目标
{
浮动4 psOut;
psOut.xyz=深度贴图样本(颜色采样器,frag.tex0).xxx;
psOut.w=1.0f;
返回psOut;
}
那么,我的实际问题是:

1) 所有这些代码编译时都没有任何问题,但当我对深度缓冲区进行采样时,结果却是黑色的。我了解到这可能是因为在您要对深度缓冲区进行采样时,深度和模具视图被
D3D11DeviceContext::OMSetRenderTargets()
绑定。我修正了,但缓冲区还是黑色的。我检查了图形调试器,但没有成功。那么,是深度缓冲区写得不正确,还是采样方式不对?firstPS_uuu工作正常

2) 说到采样,我正在使用的书只是说“我们将使用点采样器”,但我不知道它的确切含义。现在我只使用了一个标准的纹理贴图采样器,但是还有什么我应该使用的呢

3) 另外,这本书在secondPS中使用了
SamplerState.Gather()
函数,但当我尝试时,它抱怨“表达式无法映射到像素着色器指令集。”这本书中的
Gather()
是一个错误,还是我的GPU(D3D功能级别11.0)不明白这是什么?
Sample()?
Gather()
的最初用途是在深度缓冲区中的对象周围创建轮廓

4) 我试图让secondVS_u2;只画一个全屏四元组,但FXC抱怨我使用的
SV_VertexID
是“无效的”,说我的类型应该是整数,即使它已经是整数了。我在某个地方读到,
SV\u VertexID
只能由管道中的第一个VS使用。这就是问题所在吗?在这种特殊情况下,我如何解决这个问题?在我目前效率低下的解决方案中,问题是由UV引起的吗?

1)您调用了PSGetShaderResources而不是PSSetShaderResources。另外,MOSTDetailDMIP应该是0而不是-1

2) “点采样器”只是一个纹理采样器,其过滤器字段设置为类似D3D11_FILTER_MIN_MAG_MIP_point的值

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


4) 如果使用vs_4_0进行编译,则会出现此错误。请尝试vs_5_0。

是否启用了调试层?像将资源设置为输入和输出这样的错误很容易通过调试消息检测到。如果出现意外黑色,则始终是我的第一步。调试层肯定处于打开状态,所有状态创建警告都为#0。我仍然不知道出了什么问题。为什么在SRV中将MostDetailedMip设置为-1?感谢您的回答,他们都提供了帮助,尽管当我查看我的代码时,我发现MostDetailedMip已经设置为0。我真不敢相信我漏掉了那个打字错误。虽然所有内容都正确注册,但我的深度缓冲区似乎只填充了1.0f值。一旦问题解决了,我会记下你的答案。