渲染到纹理时DX11 Alpha混合

时间:2013-01-24 00:20:35

标签: c++ alphablending directx-11 render-to-texture rendertarget

最终编辑:

已解决...只需要了解alpha混合的工作原理。我应该有: oBlendStateDesc.RenderTarget [a] .DestBlendAlpha = D3D11_BLEND_ZERO; ...设置为D3D11_BLEND_ONE以保留alpha。

当渲染到后备缓冲区时,由于颜色混合正常并且这是最终输出,因此不会注意到问题。当渲染到纹理时,同样的事情适用,然后将纹理渲染到后台缓冲区,不正确的alpha会将纹理错误地混合到后台缓冲区中。

然后我遇到了另一个问题,那就是alpha似乎在减少。这是因为颜色混合了两次,例如......

Source.RBGA = 1.0f, 0.0f, 0.0f, 0.5f
Dest.RGBA   = 0.0f, 0.0f, 0.0f, 0.0f

渲染到纹理......

Result.RGB = Source.RBG * Source.A +  Dest.RGB * (1 - Source.A) = 0.5f, 0.0f, 0.0f
Result.A   = Source.A * 1 + Dest.A * 1 = 0.5f

现在...

Source.RBGA = 0.5f, 0.0f, 0.0f, 0.5f
Dest.RGBA   = 0.0f, 0.0f, 0.0f, 0.0f

渲染回后台...

Result.RGB = Source.RBG * Source.A +  Dest.RGB * (1 - Source.A) = 0.25f, 0.0f, 0.0f
Result.A = Source.A * 1 + Dest.A * 1 = 0.5f

要解决此问题,在将纹理渲染到后台缓冲区时,我使用相同的blendstate,但将SrcBlend更改为D3D11_BLEND_ONE,因此颜色不会混合两次。

希望这可以帮助其他有类似问题的人......

EDITEND

为了提高性能,我试图渲染一个永远不会变成纹理的文本字符串,以便每次都保存渲染每个字符。

由于我严格使用2D渲染,因此我禁用了深度&在进行alpha混合的同时进行模板测试。

问题是似乎没有发生任何alpha混合,最后绘制的任何内容都会用自己的数据覆盖当前像素...没有混合。

我使用单一的混合状态,我不会改变。渲染到后台缓冲区时,混合工作正常。将最终纹理渲染到后台缓冲区时,混合也可以正常工作。就在我渲染到纹理时,混合似乎失败了。

以下是我设置单一混合状态的方法:

D3D11_BLEND_DESC oBlendStateDesc;

oBlendStateDesc.AlphaToCoverageEnable = 0;
oBlendStateDesc.IndependentBlendEnable = 0; //set to false, dont need loop below... but just incase

for (unsigned int a = 0; a < 8; ++a)
{
oBlendStateDesc.RenderTarget[a].BlendEnable = 1;
oBlendStateDesc.RenderTarget[a].SrcBlend = D3D11_BLEND_SRC_ALPHA;
oBlendStateDesc.RenderTarget[a].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
oBlendStateDesc.RenderTarget[a].BlendOp = D3D11_BLEND_OP_ADD;
oBlendStateDesc.RenderTarget[a].SrcBlendAlpha = D3D11_BLEND_ONE;
oBlendStateDesc.RenderTarget[a].DestBlendAlpha = D3D11_BLEND_ZERO;
oBlendStateDesc.RenderTarget[a].BlendOpAlpha = D3D11_BLEND_OP_ADD;
oBlendStateDesc.RenderTarget[a].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
}

// Create the blend state from the description
HResult = m_poDevice->CreateBlendState(&oBlendStateDesc, &m_poBlendState_Default);

m_poDeviceContext->OMSetBlendState(m_poBlendState_Default, nullptr, 0xffffff);

在渲染到纹理时,是否还有任何额外的步骤可以启用混合?

编辑:如果我将AlphaToCoverageEnable设置为true它会混合,但看起来很糟糕。这至少证实了它使用相同的混合状态...根据渲染到后备缓冲区或纹理时的工作方式不同:/这是我的纹理描述...

m_oTexureDesc.Width = a_oDesc.m_uiWidth;
m_oTexureDesc.Height = a_oDesc.m_uiHeight;
m_oTexureDesc.MipLevels = 1;
m_oTexureDesc.ArraySize = 1;
m_oTexureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
m_oTexureDesc.SampleDesc.Count = 1; //No sampling
m_oTexureDesc.SampleDesc.Quality = 0;
m_oTexureDesc.Usage = D3D11_USAGE_DEFAULT; //GPU writes & reads
m_oTexureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
m_oTexureDesc.CPUAccessFlags = 0;
m_oTexureDesc.MiscFlags = 0;

编辑: 这是一些可视化...... Text

  1. 渲染到后备缓冲区 - 启用AlphaBlending。
  2. 渲染到纹理 - 启用AlphaBlending。
  3. 渲染到后备缓冲区 - 禁用AlphaBlending。
  4. 字母T取自字体文件
  5. *禁用AB时渲染,字母完全匹配(比较4&amp; 3)

    *在启用AB的情况下渲染到后备缓冲区时,字母呈现略微(几乎不可察觉)被淘汰但仍然混合(比较4&amp; 1)

    *当渲染到启用了AB的纹理时,字母渲染得更加明显,而不是完全混合。 (比较4&amp; 2)

    不确定为什么颜色会在启用Alpha混合的情况下被淘汰......但也许是一个线索?

    编辑: 如果我清除渲染目标纹理说... 0.0f,0.0f,1.0f,1.0f(RGBA,蓝色)...这是结果: enter image description here

    只有alpha&gt;的像素0.0f&amp; &LT; 1.0f与颜色混合。另一条线索,但我不知道如何解决这个问题...

0 个答案:

没有答案