Direct3D 11 проблема глубины трафарета / альфа-смешения

Я работал над 3D-рендерингом для игры, и до сих пор он рендерил сначала все неструктурированные сетки, а затем все текстурированные сетки, используя DrawIndexed. Чтобы улучшить производительность, я переключился на DrawIndexedInstanced и сделал так, чтобы сначала отображались текстурированные сетки, и это выявило проблему с настройкой альфа-смешивания и / или проверки глубины. Следующие изображения должны иллюстрировать, в чем проблема:

Просмотр через верхнюю часть передних текстур (текстурированные сетки визуализируются первыми)

Тот же самый вид, немного другой угол (текстуры без текстуры отображаются первыми)

На переднем плане и на заднем плане расположены ряды текстурированных прямоугольных сеток, а на переднем плане частично прозрачные сетки. В среднем ряду нетекстурированные сетки с прозрачностью 0,3f. Когда текстурированные сетки визуализируются первыми, нетекстурированные маски затеняются прозрачными сетками на переднем плане. Однако, когда первыми визуализируются нетекстурированные сетки, они полностью скрывают текстурированные сетки позади них, даже когда их прозрачность составляет 0,3f. Этого не происходит, когда нетекстурированные сетки затеняют другие нетекстурированные сетки, альфа-смешение работает правильно в этом сценарии.

Здесь я настраиваю состояние растеризатора, состояние шаблона глубины и представление шаблона глубины:

ID3D11Texture2D *pBackBuffer;
D3D11_TEXTURE2D_DESC backBufferDesc;
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
pBackBuffer->GetDesc(&backBufferDesc);
RELEASE_RESOURCE(pBackBuffer);

// creating a buffer for the depth stencil
D3D11_TEXTURE2D_DESC depthStencilBufferDesc;
ZeroMemory(&depthStencilBufferDesc, sizeof(D3D11_TEXTURE2D_DESC));

depthStencilBufferDesc.ArraySize = 1;
depthStencilBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilBufferDesc.CPUAccessFlags = 0; // No CPU access required.
depthStencilBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilBufferDesc.Width = backBufferDesc.Width;
depthStencilBufferDesc.Height = backBufferDesc.Height;
depthStencilBufferDesc.MipLevels = 1;
depthStencilBufferDesc.SampleDesc.Count = 4;
depthStencilBufferDesc.SampleDesc.Quality = 0;
depthStencilBufferDesc.Usage = D3D11_USAGE_DEFAULT;
m_device->CreateTexture2D(&depthStencilBufferDesc, NULL, &m_depthStencilBuffer);

// creating a depth stencil view
HRESULT hr = m_device->CreateDepthStencilView(  m_depthStencilBuffer,
NULL,
&m_depthStencilView);// setup depth stencil state.
D3D11_DEPTH_STENCIL_DESC depthStencilStateDesc;
ZeroMemory(&depthStencilStateDesc, sizeof(D3D11_DEPTH_STENCIL_DESC));

depthStencilStateDesc.DepthEnable = TRUE;
depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthStencilStateDesc.StencilEnable = FALSE;

hr = m_device->CreateDepthStencilState(&depthStencilStateDesc, &m_depthStencilState);

// setup rasterizer state.
D3D11_RASTERIZER_DESC rasterizerDesc;
ZeroMemory(&rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));

rasterizerDesc.AntialiasedLineEnable = FALSE;
rasterizerDesc.CullMode = D3D11_CULL_BACK;
rasterizerDesc.DepthBias = 0;
rasterizerDesc.DepthBiasClamp = 0.0f;
rasterizerDesc.DepthClipEnable = TRUE;
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.FrontCounterClockwise = FALSE;
rasterizerDesc.MultisampleEnable = FALSE;
rasterizerDesc.ScissorEnable = FALSE;
rasterizerDesc.SlopeScaledDepthBias = 0.0f;

// create the rasterizer state
hr = m_device->CreateRasterizerState(&rasterizerDesc, &m_RasterizerState);

m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);
m_deviceContext->RSSetState(m_RasterizerState);

И здесь я включаю альфа-смешение:

D3D11_BLEND_DESC blendDescription;
ZeroMemory(&blendDescription, sizeof(D3D11_BLEND_DESC));
blendDescription.RenderTarget[0].BlendEnable = TRUE;
blendDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blendDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
blendDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
m_device->CreateBlendState(&blendDescription, &m_blendState);
m_deviceContext->OMSetBlendState(m_blendState, 0, 0xffffffff);

Я знаю, что придание бесцветной сетке простой белой полностью непрозрачной текстуры решило бы проблему в некотором роде, но я подозреваю, что тестирование глубины является ошибочным.

Когда я создаю устройство с флагом D3D11_CREATE_DEVICE_DEBUG, оно не дает мне ошибок или предупреждений.

Все HRESULT, возвращаемые функциями Create, являются S_OK.

Заранее спасибо.

0

Решение

Чтобы смешивание работало, вы должны сначала отобразить все полностью непрозрачные объекты, а затем все объекты с прозрачностью в обратном порядке. Это означает, что ваши прозрачные объекты сортируются в зависимости от расстояния до камеры с более дальними объектами в первую очередь.

В идеале ваши непрозрачные объекты сортируются в противоположном направлении (спереди назад), так что затемненные пиксели отбрасываются тестом глубины.

Обычно это делается путем помещения всех запросов на рисование в очередь. Когда все в сцене находится в очереди, вы можете отсортировать его по различным факторам, включая прозрачность, расстояние, материал и т. Д. Затем вы можете пройтись по очереди и выполнить все ваши запросы на отрисовку в правильном порядке.

Для простых случаев, однако, просто убедитесь, что ваши непрозрачные объекты нарисованы первыми, а прозрачные объекты нарисованы в общем порядке в обратном порядке.

0

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

Других решений пока нет …

По вопросам рекламы [email protected]