Проблемы с выборкой буфера глубины D3D11

Я готовлю все в небольшом моем 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_ и 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 11.0), который не понимает, что это такое? Является Sample() достаточно хорош для того, что я хочу сделать? Первоначальное использование Gather() был в контексте создания силуэта вокруг объектов в буфере глубины.

4) Я пытался заставить secondVS_ рисовать только полноэкранный квад, но FXC жаловался на мое использование SV_VertexID как «недействительный», говоря, что мой тип должен быть целым, даже если он уже был. Я где-то читал, что SV_VertexID может использоваться только первым VS в конвейере. Это проблема здесь? Как мне решить это в данном конкретном случае? В моем текущем неэффективном решении, проблема вызвана ультрафиолетом?

1

Решение

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.

1

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector