2017-05-06 24 views
0

저는 게임용 3D 렌더러에서 작업 해 왔으며, 지금까지는 DrawIndexed를 사용하여 모든 텍스처리스 메시와 모든 텍스처 메시를 렌더링했습니다. 성능 향상을 위해 DrawIndexedInstanced로 전환하여 텍스처 메쉬가 먼저 렌더링되도록 했으므로 알파 블렌딩 및/또는 깊이 검사 설정 방법에 문제가 발생했습니다. 전경과 배경에Direct3D 11 스텐실/알파 블렌딩 문제

View through the top of the front-most textures (textured meshes rendered first)

The same view, slightly different angle (textureless meshes rendered first)

는 질감 사각형 메쉬의 행, 그리고 전경에있는 사람은 부분적으로 투명 메쉬를 다음 이미지는 문제가 무엇인지 설명한다. 중간 행에는 텍스처가없는 메쉬가 있으며 투명도는 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 플래그로 장치를 만들면 오류 또는 경고가 표시되지 않습니다.

Create 함수가 반환 한 모든 HRESULT는 S_OK입니다.

미리 감사드립니다.

답변

0

블렌드를 사용하려면 완전히 불투명 한 모든 객체를 먼저 렌더링 한 다음 투명도가있는 모든 객체를 맨 앞에서 순서대로 렌더링해야합니다. 즉, 투명 물체는 멀리있는 물체가있는 카메라로부터의 거리를 기준으로 정렬됩니다.

어둡게 표시된 픽셀이 깊이 테스트에서 제외되도록 불투명 한 오브젝트가 반대 방향 (앞에서 뒤로)으로 정렬되는 것이 가장 이상적입니다.

이것은 일반적으로 모든 그리기 요청을 대기열에 배치하여 수행됩니다. 장면의 모든 내용이 대기열에 있으면 투명도, 거리, 재질 등을 비롯한 다양한 요소를 기준으로 정렬 할 수 있습니다. 그런 다음 대기열을 순환하여 모든 순서 요청을 올바른 순서로 처리 할 수 ​​있습니다.

그러나 단순한 경우에는 불투명 한 객체가 먼저 표시되고 투명한 객체가 일반적으로 앞뒤 순서로 그려 지도록하십시오.

+0

그럼 명확히하기 위해 깊이 테스트와 알파 블렌딩을 설정 한 방법에 문제가 있습니까? –

+0

그들은 나에게 잘 보입니다. – megadan

+0

투명 오브젝트를 먼저 렌더링하면 블렌드 할 것이 없으므로 불투명하게 보입니다. 또한 z 값을 깊이 버퍼에 씁니다.다음에 렌더링하는 객체가 투명 객체 뒤에있는 경우에는 깊이 테스트로 인해 가려진 픽셀이 그려지지 않습니다.이 깊이 테스트는 현재 z 값이 더 가까운 픽셀과 현재 깊이 버퍼에있는 픽셀 만 허용합니다. – megadan