J'ai travaillé sur un moteur de rendu 3D pour un jeu, et jusqu'à présent, il a rendu toutes les maillages sans texture et toutes les maillages texturés après, en utilisant DrawIndexed. Dans un effort pour améliorer les performances, je suis passé à DrawIndexedInstanced et fait en sorte que les maillages texturés sont rendus en premier, et cela a révélé un problème avec la façon dont mon alpha blending et/ou vérification de profondeur est mis en place. Les images suivantes illustrent le problème est:Direct3D 11 profondeur pochoir/alpha mélange problème
View through the top of the front-most textures (textured meshes rendered first)
The same view, slightly different angle (textureless meshes rendered first)
Au premier plan, et l'arrière-plan sont des rangées de mailles rectangle texture, et ceux de premier plan ont des mailles partiellement transparentes. Dans la rangée du milieu sont des maillages non texturés avec leur transparence réglée sur 0.3f. Lorsque les maillages texturés sont rendus en premier, ceux non texturés sont masqués par les maillages transparents au premier plan. Cependant, quand ce sont les maillages non texturés qui sont rendus en premier, ils masquent complètement les maillages texturés derrière eux, même quand leur transparence est à 0.3f. Cela ne se produit pas lorsque des maillages non texturés masquent d'autres maillages non texturés, le mélange alpha fonctionne correctement dans ce scénario.
C'est là que je mis en place l'état de rastérisation, l'état de pochoir de profondeur et vue pochoir profondeur:
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);
Et c'est là activer le mélange alpha:
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);
Je sais que donner la Un maillage sans texture Une texture entièrement opaque et blanche permettrait de résoudre le problème, mais je suppose que le test de profondeur est en cause. Lorsque je crée l'appareil avec l'indicateur D3D11_CREATE_DEVICE_DEBUG, il ne me donne pas d'erreurs ou d'avertissements.
Tous les HRESULTs renvoyés par les fonctions Create sont S_OK.
Merci d'avance.
Juste pour clarifier alors, n'y a-t-il rien de mal dans la façon dont j'ai mis en place mes tests de profondeur et alpha blending? –
Ils me vont bien. – megadan
Si vous rendez d'abord un objet transparent, il n'a rien à mélanger, il apparaîtra donc opaque. En outre, il écrira sa valeur z dans le tampon de profondeur.Si l'objet suivant est derrière l'objet transparent, les pixels masqués ne seront pas dessinés en raison du test de profondeur qui n'autorisera que les pixels avec des valeurs z plus proches que ce qui est actuellement dans le tampon de profondeur. – megadan