最终编辑:
已解决...只需要深入了解 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
为了解决这个问题,在将纹理渲染到后台缓冲区时,我使用相同的混合状态,但将 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);
在渲染到纹理时,我是否缺少任何额外的步骤来启用混合?
编辑:如果我将 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;
编辑:这是一些可视化...
- 渲染到后备缓冲区 - 启用 AlphaBlending。
- 渲染到纹理 - 启用 AlphaBlending。
- 渲染到后备缓冲区 - 禁用 AlphaBlending。
- 取自字体文件的字母 T
*当禁用 AB 渲染时,字母完全匹配(比较 4 和 3)
*在启用 AB 的情况下渲染到后台缓冲区时,字母渲染略微(几乎不明显)褪色但仍然混合(比较 4 和 1)
*在启用 AB 的情况下渲染到纹理时,字母渲染得更加明显,而根本没有混合。(比较 4 和 2)
不知道为什么颜色会在启用 alpha 混合的情况下被洗掉......但也许它是一个线索?
编辑:如果我清除渲染目标纹理说...... 0.0f,0.0f,1.0f,1.0f(RGBA,蓝色)......这是结果:
只有 alpha > 0.0f & < 1.0f 的像素与颜色混合。另一个线索,但我不知道如何解决这个问题......