Я готовлю все в небольшом проекте DirectX 11.0 для отложенного конвейера рендеринга. Тем не менее, у меня было довольно много проблем с выборкой буфера глубины из пиксельного шейдера.Проблемы с выборкой D3D11 буфера глубины
Сначала я определить текстуру глубины и его вид ресурса шейдера:
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) Все это код компилируется без каких-либо проблем, но когда я попробовать буфер глубины, он просто оказывается черным. Я читал, что это может быть вызвано тем, что ваша глубина &: просмотр трафарета связан D3D11DeviceContext::OMSetRenderTargets()
во время выбора буфера глубины. Я исправил это, но буфер все еще черный. Я проверил графический отладчик, без успеха. Итак, мой буфер глубины не получается правильно написанным, или я неправильно пробовал? firstPS_ отлично работает.
2) Говоря о выборке, книга, которую я использую, просто говорит: «Мы будем использовать точечный сэмплер», но я понятия не имею, что именно имеется в виду. Теперь я просто использую стандартный сэмплер текстурной карты, но есть ли что-то еще, что я должен попробовать?
3) Кроме того, книга использует функцию SamplerState.Gather()
в secondPS_, но когда я попробовал, он пожаловался, что «выражение не может быть отображено в набор инструкций пиксельных шейдеров». Является ли Gather()
ошибкой в книге, или это мой графический процессор (D3D feature level 11.0), который не понимает, что это такое? Является ли Sample()
достаточным для того, что я хочу делать? Первоначальное использование Gather()
было в контексте создания силуэта вокруг объектов в буфере глубины.
4) Я попытался получить secondVS_, чтобы нарисовать ничего, кроме полноэкранного четырехъядерного процессора, но FXC жаловался на то, что мое использование SV_VertexID
было «недействительным», заявив, что мой тип должен быть интегральным, даже если он уже был. Я где-то читал, что SV_VertexID
может использоваться только первым VS в конвейере. Это проблема здесь? Как я могу решить это в этом конкретном случае? В моем текущем неэффективном решении проблема связана с УФ?
Включили ли вы слой отладки? Такие ошибки, как установка ресурса как ввода, так и вывода, очень легко обнаружить с помощью отладочных сообщений. Всегда мой первый шаг, если что-то возвращает неожиданный черный цвет. – Gnietschow
Уровень отладки включен, и все предупреждения создания состояния - # 0. Я до сих пор не знаю, что происходит. – PeanutsGrowUnderground
Почему параметр MostDetailedMip установлен на -1 в SRV? –