2017-05-06 2 views
0

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.

Antwort

0

Damit eine Überblendung funktioniert, müssen Sie zunächst alle vollständig deckenden Objekte und dann alle Objekte mit Transparenz in umgekehrter Reihenfolge darstellen. Dies bedeutet, dass Ihre transparenten Objekte basierend auf der Entfernung von der Kamera mit weiteren Objekten zuerst sortiert werden.

Idealerweise sind Ihre undurchsichtigen Objekte in der entgegengesetzten Richtung (von vorne nach hinten) sortiert, so dass Pixel, die verdeckt sind, durch den Tiefentest verworfen werden.

Dies geschieht normalerweise, indem alle Zeichenanforderungen in eine Warteschlange gestellt werden. Sobald sich alles in der Szene in der Warteschlange befindet, können Sie sie anhand verschiedener Faktoren wie Transparenz, Entfernung, Material usw. sortieren. Anschließend können Sie die Warteschlange durchlaufen und alle Ihre Zeichnungsanfragen in der richtigen Reihenfolge ausführen.

Für einfache Fälle, stellen Sie nur sicher, dass Ihre undurchsichtigen Objekte zuerst gezeichnet werden und Ihre transparenten Objekte als nächste in einer allgemeinen Reihenfolge von vorne nach hinten gezeichnet werden.

+0

Nur um zu verdeutlichen, gibt es nichts falsch daran, wie ich meine Tiefentests und Alpha-Blending eingerichtet habe? –

+0

Sie sehen ok für mich aus. – megadan

+0

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