Ben*_*n Y 5 c++ alphablending directx-11 render-to-texture rendertarget
最终编辑:
已解决...只需深入了解 alpha 混合如何工作。我应该有: oBlendStateDesc.RenderTarget[a].DestBlendAlpha = D3D11_BLEND_ZERO; ...设置为 D3D11_BLEND_ONE 以保留 Alpha。
当渲染到后台缓冲区时,问题不会被注意到,因为颜色混合正常,这就是最终输出。当渲染到纹理时,同样的情况也适用,然后将纹理渲染到后缓冲区,不正确的 alpha 会导致错误地将纹理混合到后缓冲区。
然后我遇到了另一个问题,阿尔法似乎在减少。这是因为颜色混合了两次,例如......
Source.RBGA = 1.0f, 0.0f, 0.0f, 0.5f
Dest.RGBA = 0.0f, 0.0f, 0.0f, 0.0f
Run Code Online (Sandbox Code Playgroud)
渲染成纹理...
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
Run Code Online (Sandbox Code Playgroud)
现在...
Source.RBGA = 0.5f, 0.0f, 0.0f, 0.5f
Dest.RGBA = 0.0f, 0.0f, 0.0f, 0.0f
Run Code Online (Sandbox Code Playgroud)
渲染到后台缓冲区...
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
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,当将纹理渲染到后缓冲区时,我使用相同的混合状态,但将 SrcBlend 更改为 D3D11_BLEND_ONE,这样颜色就不会混合两次。
希望这可以帮助其他遇到类似问题的人......
编辑
为了提高性能,我尝试渲染一串永远不会更改为纹理的文本,以节省每次渲染每个单独的字符。
由于我严格以 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);
Run Code Online (Sandbox Code Playgroud)
渲染到纹理时是否缺少任何额外步骤来启用混合?
编辑:如果我将 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;
Run Code Online (Sandbox Code Playgroud)
编辑:这是一些可视化......

*在禁用 AB 的情况下进行渲染时,字母完全匹配(比较 4 和 3)
*在启用 AB 的情况下渲染到后台缓冲区时,字母渲染会稍微(几乎不明显)褪色,但仍然混合(比较 4 和 1)
*当渲染到启用 AB 的纹理时,字母渲染得更明显,但根本不混合。(比较 4 和 2)
不知道为什么启用 Alpha 混合后颜色会被冲掉……但也许这是一个线索?
编辑:如果我清除渲染目标纹理说...0.0f,0.0f,1.0f,1.0f(RGBA,蓝色)...这就是结果:

只有 alpha > 0.0f 和 < 1.0f 的像素才会与颜色混合。另一个线索,但我不知道如何解决这个问题......