Direct3d 11深度模板 / Alpha混合问题

Direct3D 11 depth stencil / alpha blending issue

本文关键字:Alpha 混合 问题 深度 Direct3d      更新时间:2023-10-16

我一直在为游戏制作3D渲染器,直到现在,它首先使用drawIndexexed渲染了所有纹理网格和所有纹理网格。为了提高性能,我改用了DrawIndexedInstance,并制作了它,以便首先呈现纹理的网格,这揭示了如何设置Alpha混合和/或深度检查的问题。以下图像应说明问题是什么:

通过最前面纹理的顶部(首先渲染的纹理网格(查看

相同的视图,略有不同的角度(首先渲染的无纹理网格(

在前景和背景中是纹理矩形网的行,前景中的矩形网络具有部分透明的网格。在中间排是未纹理的网格,其透明度设置为0.3F。当首先呈现纹理网格时,未纹理的网格被前景中的透明网格遮盖了。但是,当首先渲染的不介入的网眼时,即使它们的透明度为0.3F,它们也完全掩盖了它们背后的纹理网格。当不介绍的网眼掩盖了其他未纹理的网格时,这不会发生这种情况,在这种情况下,Alpha混合起作用。

这是我设置栅格态,深度模板状态和深度模板视图的地方:

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);

这就是我启用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);

我知道,给无纹理的网眼纯白色完全不透明的纹理会以某种方式解决该问题,但我怀疑深度测试是错误的。

当我使用d3d11_create_device_debug标志创建设备时,它不会给我任何错误或警告。

创建功能返回的所有hresults均为s_ok。

预先感谢。

要混合工作,您必须先渲染所有完全不透明的对象,然后在背对面上以透明度为单位。这意味着您的透明对象是根据与较远对象的距离距离的距离进行排序的。

理想情况下,您的不透明对象以相反的方向(前后(排序,因此被遮盖的像素被深度测试丢弃。

这通常是通过将所有拉动请求放入队列中来完成的。一旦场景中的所有内容都在队列中,您就可以根据各种因素进行对其进行排序

对于简单的情况,只需确保首先绘制不透明的对象,然后在一般回到前订单中绘制透明对象。