2017-05-06 8 views
0

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.

Répondre

0

Pour que le fondu fonctionne, vous devez d'abord rendre tous les objets totalement opaques, puis tous les objets avec transparence dans un ordre inverse. Cela signifie que vos objets transparents sont triés en fonction de la distance de la caméra avec les objets les plus éloignés.

Idéalement, vos objets opaques sont triés dans la direction opposée (avant à arrière) de sorte que les pixels qui sont obscurcis soient éliminés par le test de profondeur. Ceci est généralement effectué en plaçant toutes les demandes de dessin dans une file d'attente. Une fois que tous les éléments de la scène sont dans la file, vous pouvez les trier en fonction de divers facteurs, notamment la transparence, la distance, le matériel, etc. Vous pouvez ensuite parcourir la file d'attente et placer toutes vos demandes de tirage dans le bon ordre. Cependant, pour les cas simples, assurez-vous simplement que vos objets opaques sont dessinés en premier et que vos objets transparents sont dessinés dans un ordre général d'arrière en avant.

+0

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? –

+0

Ils me vont bien. – megadan

+0

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