Ich habe an einem 3D-Renderer für ein Spiel gearbeitet, und bis jetzt wurden alle texturless Meshes zuerst und alle texturierten Meshes danach mit DrawIndexed gerendert. Um die Leistung zu verbessern, habe ich zu DrawIndexedInstanced gewechselt und dafür gesorgt, dass texturierte Meshes zuerst gerendert werden. Dies hat ein Problem mit der Einstellung meiner Alpha Blending- und/oder Tiefenprüfung ergeben. Die folgenden Bilder sollen veranschaulichen, was das Problem ist:Direct3D 11 Tiefe Schablone/Alpha Blending Problem
View through the top of the front-most textures (textured meshes rendered first)
The same view, slightly different angle (textureless meshes rendered first)
Im Vordergrund und Hintergrund sind Reihen von strukturierten Rechteck Maschen, und die, die im Vordergrund haben teilweise transparente Maschen. In der mittleren Reihe sind untexturierte Meshes mit einer Transparenz von 0.3f. Wenn texturierte Netze zuerst gerendert werden, werden die nicht strukturierten durch die transparenten Gitter im Vordergrund verdeckt. Wenn es jedoch die untexturierten Netze sind, die zuerst gerendert werden, verdecken sie die texturierten Netze hinter ihnen vollständig, selbst wenn ihre Transparenz bei 0,3f liegt. Dies passiert nicht, wenn nicht texturierte Meshes andere untexturierte Meshes verdecken, Alpha-Blending funktioniert in diesem Szenario korrekt.
Dies ist, wo ich die Rasterizer Zustand, Tiefe Schablonen Zustand und Tiefe Schablonenansicht ein:
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);
Und das ist, wo ich Alpha-Blending zu aktivieren:
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);
Ich weiß, dass was die texturless mesh eine einfache weiße vollständig undurchsichtige Textur würde das Problem auf eine Art und Weise beheben, aber ich vermute, dass die Tiefenprüfung fehlerhaft ist.
Wenn ich das Gerät mit dem D3D11_CREATE_DEVICE_DEBUG-Flag erstellen, gibt es mir keine Fehler oder Warnungen.
Alle von den Create-Funktionen zurückgegebenen HRESULTs sind S_OK.
Vielen Dank im Voraus.
Nur um zu verdeutlichen, gibt es nichts falsch daran, wie ich meine Tiefentests und Alpha-Blending eingerichtet habe? –
Sie sehen ok für mich aus. – megadan
Wenn Sie zuerst ein transparentes Objekt rendern, hat es nichts zu vermischen, so dass es undurchsichtig erscheint. Außerdem wird es seinen z-Wert in den Tiefenpuffer schreiben.Wenn das nächste Objekt, das Sie rendern, hinter dem transparenten Objekt liegt, werden die verdeckten Pixel wegen des Tiefentests nicht gezeichnet, was nur Pixel mit näher liegenden z-Werten zulässt, als das aktuell im Tiefenpuffer ist. – megadan