我如何正确地渲染深度信息在D3D11阴影贴图单独通过?



所以我想在我的D3D11渲染器中实现阴影。然而,调试层给了我一个警告

D3D11 WARNING: ID3D11DeviceContext::OMSetRenderTargets: Resource being set to OM DepthStencil is still bound on input! [ STATE_SETTING WARNING #9: DEVICE_OMSETRENDERTARGETS_HAZARD]
D3D11 WARNING: ID3D11DeviceContext::OMSetRenderTargets[AndUnorderedAccessViews]: Forcing PS shader resource slot 1 to NULL. [ STATE_SETTING WARNING #7: DEVICE_PSSETSHADERRESOURCES_HAZARD]
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 1, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults.  [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]
D3D11 WARNING: ID3D11DeviceContext::DrawIndexed: The Pixel Shader unit expects a Sampler to be set at Slot 1, but none is bound. This is perfectly valid, as a NULL Sampler maps to default Sampler state. However, the developer may not want to rely on the defaults.  [ EXECUTION WARNING #352: DEVICE_DRAW_SAMPLER_NOT_SET]

相关代码如下:

void AppWindow::renderShadowMap()
{
//GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->unbindSRV();
//CLEAR THE RENDER TARGET AND DEPTH STENCIL
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->clearRenderTargetColor(shadow_map_rtv, 1.0, 1.0f, 1.0f, 1);
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->clearDepthStencil(shadow_map_dsv);
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->SetRenderTarget(shadow_map_rtv, shadow_map_dsv);
//SET VIEWPORT OF RENDER TARGET IN WHICH WE HAVE TO DRAW
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->setViewportSize(1920, 1080);
lightViewMatrix = Matrix4x4::lookAt(Vector3D(2,2,0), Vector3D(0, 0, 0), Vector3D(0, 1, 0));
lightProjectionMatrix.setOrthoProj(20, 20, 1.0f, 10.0f);
lightSpaceMatrix = lightProjectionMatrix;
lightSpaceMatrix *= lightViewMatrix;
updateModel(Vector3D(0, 0, 0), MAT_shadow_map);
SM_mesh->drawMesh(MAT_shadow_map);
updateModel(Vector3D(0, -0.5f, 0), MAT_shadow_map);
SM_plane->drawMesh(MAT_shadow_map);
SM_sky_mesh->drawMesh(MAT_shadow_map);
//GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->SetRenderTarget(NULL, NULL);
}
void AppWindow::render()
{
//CLEAR THE RENDER TARGET 
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->clearRenderTargetColor(this->m_swap_chain, 0.3f, 0.4f, 0.5f, 1);
//SET VIEWPORT OF RENDER TARGET IN WHICH WE HAVE TO DRAW
RECT rc = this->getClientWindowRect();
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->setViewportSize(rc.right - rc.left, rc.bottom - rc.top);
update();
updateModel(Vector3D(0, 0, 0), MAT_mesh);
SM_mesh->drawMesh(MAT_mesh);
updateModel(Vector3D(0, -0.5f, 0), MAT_mesh);
SM_plane->drawMesh(MAT_mesh);
SM_sky_mesh->drawMesh(MAT_sky);
m_swap_chain->present(true);
oldDelta = newDelta;
newDelta = ::GetTickCount();
deltaTime = (oldDelta) ? ((newDelta - oldDelta) / 1000.0f) : 0.0f;
time += deltaTime;
GraphicsEngine::get()->getRenderSystem()->getImmediateDeviceContext()->unbindSRV();
}
void DeviceContext::unbindSRV()
{
ID3D11ShaderResourceView* nullSRV[1] = { nullptr };
m_device_context->PSSetShaderResources(0, 1, nullSRV);
}

我只需要知道如何以及在哪里解除shadow_map_rtvshadow_map_dsv的绑定,因为这就是导致问题的原因。在网上找不到类似的

我猜你的阴影贴图渲染管道是错误的。首先,您应该将渲染目标设置为nullptr或NULL。然后创建并绑定阴影贴图的深度模板。然后清除深度模板,从光视图渲染场景。如果你的程序中有任何相机类,你可以为光线创建另一个相机。您可以使用深度模板输出纹理作为阴影映射着色器的阴影贴图。所有其他的东西,如采样器或原始拓扑是可选的渲染管道。我将放置一段代码。

ID3D11RenderTargetView* rtv[1] = { 0 };
pContext->OMSetRenderTargets(1, rtv, dsShadow->pDepthStencilView.Get());
dsShadow->Clear(pContext.Get());
RenderScene(pDirectLight->GetLightCamera());

在警告消息中,似乎您正在将阴影映射设置为槽1(当绑定在像素着色器中读取时)。

但是你的unbindSRV函数只清除槽0,所以很可能你的阴影地图仍然绑定在那里,当你设置它写(通过SetRenderTarget)。

按照这个顺序是可以的,因为管道会为你取消分配Shader资源视图(并发出警告),但通常让管道高兴是很好的做法(你可能会错过重要的警告)。

所以你应该让这个函数工作在:

void DeviceContext::unbindSRV(int slot)
{
ID3D11ShaderResourceView* nullSRV[1] = { nullptr };
m_device_context->PSSetShaderResources(slot, 1, nullSRV);
}

或者在相关的情况下同时执行多个解绑定,例如:

ID3D11ShaderResourceView* nullSRV[2] = { nullptr, nullptr  };
m_device_context->PSSetShaderResources(0, 2, nullSRV);

第二个选项通常更有效。

对于采样器问题,似乎您确实没有附加采样器状态(它也在槽1中,所以也许您错误地将一个设置为槽0)

用你想要的设置创建一个,然后分配也是一个很好的做法。

最新更新