DirectX 图像纹理四边形在透明的地方显示底层控件颜色

Posted

技术标签:

【中文标题】DirectX 图像纹理四边形在透明的地方显示底层控件颜色【英文标题】:DirectX Image texture quad displays underlying controls color where it is transparent 【发布时间】:2017-01-30 21:38:42 【问题描述】:

我正在尝试在纹理上绘制纹理,如下图所示。

黄色圆圈图片:

绿色圆圈图片:

如上面的企鹅图像所示,我正在尝试将另一张图像渲染为由绿色和黄色圆圈显示的纹理。图像在显示紫色的地方是透明的。紫色是绘制纹理的基础控件的颜色。

渲染顺序为: 1.渲染企鹅 2.渲染绿色圆圈 3.渲染黄色圆圈 4. 渲染绿色圆圈

现在我不确定为什么我会看到绿色/黄色圆圈图像的紫色?

通过测试我发现,如果我不设置混合因子并使用不同的图像作为具有 alpha 值的叠加图像,那么它可以正常工作。因此,当我使用 alpha 值为 0 的图像时,似乎有些事情发生了。

数周以来我一直在试图找出这背后的原因,但无法弄清楚它的原因。

有什么建议或可以指引我走向正确的方向吗?

注意:将 Directx11 与 ShapDx 一起使用

附:我也在另一个论坛here 上发布了这个问题,但到目前为止还没有运气。

编辑: 渲染背景企鹅图像后启用混合状态的代码

        var renderTargetDesc = new RenderTargetBlendDescription();
        renderTargetDesc.IsBlendEnabled = true;
        renderTargetDesc.SourceBlend = BlendOption.SourceAlpha;
        renderTargetDesc.DestinationBlend = BlendOption.InverseSourceAlpha;
        renderTargetDesc.BlendOperation = BlendOperation.Add;
        renderTargetDesc.SourceAlphaBlend = BlendOption.One;
        renderTargetDesc.DestinationAlphaBlend = BlendOption.Zero;
        renderTargetDesc.AlphaBlendOperation = BlendOperation.Add;
        renderTargetDesc.RenderTargetWriteMask = ColorWriteMaskFlags.All;

        BlendStateDescription desc = new BlendStateDescription();
        desc.AlphaToCoverageEnable = false;
        desc.IndependentBlendEnable = false;

        if (m_blendStateEnabled == null)
        
            m_blendStateEnabled = new BlendState(m_Dx11Device, desc);
        

        desc.RenderTarget[0] = renderTargetDesc;
        desc.RenderTarget[1] = renderTargetDesc;

        m_Dx11Device.ImmediateContext.OutputMerger.BlendState = m_blendStateEnabled;
        m_Dx11Device.ImmediateContext.OutputMerger.BlendFactor = new Color4(0, 0, 0, 0);
        m_Dx11Device.ImmediateContext.OutputMerger.BlendSampleMask = 0x0F;

附:编辑: 我一直在尝试通过尝试缩小范围来尝试不同的方法,我可以总结混合工作,但没有像预期的那样,但已经设法缩小范围。

尝试在画中画上渲染图像时:

首先,我在一个类中分离了所有四边形的绘制。使用这个类,我可以通过调用几个函数来绘制尽可能多的对象,包括在绘制调用中设置以下内容:

DxDevice.ImmediateContext.InputAssembler.InputLayout = m_shaderData.InputLayoutConfig;
DxDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

SetVertexBuffer();

DxDevice.ImmediateContext.VertexShader.Set(m_shaderData.VertexShaderConfig);
DxDevice.ImmediateContext.PixelShader.Set(m_shaderData.PixelShaderConfig);

DxDevice.ImmediateContext.Draw(4, 0);

现在,通过广泛的测试和玩耍,我发现:

    我有一个绘制背景的四边形对象和一个单独的四边形对象来绘制标志 png。使用这种方式,png 将显示实际的控件颜色。

现在,如果我启用 AlphaBlending,我得到的只是填充标志 png 四边形的灰色。同样为此,我尝试更新渲染当我对纹理进行采样时返回的 rgb 颜色: ShaderTexture.Sample(Sampler, input.TextureUV); 返回的颜色是黑色:r=1, g=1, b= 1, a= 1

    如果我重复使用与绘制背景图像相同的四边形对象,然后绘制标志 png,则我的背景图像将绘制在代表标志 png 的四边形内的标志 png 下方,而我的背景图像不是四边形在更大的四边形上。

现在从上面(在第 2 点找到);如果我使用新的四边形绘制,似乎混合不起作用。

任何想法为什么会发生这种情况?

【问题讨论】:

你的 blendstate 对象的混合模式是什么,半透明应该是 src_alpha + inv_src_alpha ? @galop1n 我添加了我用来启用 alpha 混合的代码。但是,这不起作用。 【参考方案1】:

好的,我得到了这个工作。

我使用以下步骤执行:

        var renderTargetDesc = new RenderTargetBlendDescription();
        renderTargetDesc.IsBlendEnabled = true;
        renderTargetDesc.SourceBlend = BlendOption.SourceAlpha;
        renderTargetDesc.DestinationBlend = BlendOption.InverseSourceAlpha;
        renderTargetDesc.BlendOperation = BlendOperation.Add;
        renderTargetDesc.SourceAlphaBlend = BlendOption.Zero;
        renderTargetDesc.DestinationAlphaBlend = BlendOption.One;
        renderTargetDesc.AlphaBlendOperation = BlendOperation.Add;
        renderTargetDesc.RenderTargetWriteMask = ColorWriteMaskFlags.All;

        BlendStateDescription desc = new BlendStateDescription();
        desc.AlphaToCoverageEnable = false;
        desc.IndependentBlendEnable = false;
        desc.RenderTarget[0] = renderTargetDesc;

        var blendStateEnabled = new BlendState(DxDevice, desc);

        var blendFactor = new Color4(0, 0, 0, 0);
        var iSampleMask = ~0;
        DxDevice.ImmediateContext.OutputMerger.SetBlendState(blendStateEnabled, blendFactor, iSampleMask);

        UpdateShaderResource();

        DxDevice.ImmediateContext.InputAssembler.InputLayout = m_shaderData.InputLayoutConfig;
        DxDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

        SetVertexBuffer();

        DxDevice.ImmediateContext.VertexShader.Set(m_shaderData.VertexShaderConfig);
        DxDevice.ImmediateContext.PixelShader.Set(m_shaderData.PixelShaderConfig);

        DxDevice.ImmediateContext.OutputMerger.BlendState = null;

【讨论】:

【参考方案2】:

这是因为当你渲染你的圆圈时,像素 alpha 也会写入,如果你的最终合成图像必须是不透明的,你可以使用 RGBX8 表面,或者在混合状态写入颜色掩码时屏蔽掉 alpha 通道,并且请务必将其清除为白色:

renderTargetDesc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL & ~D3D11_COLOR_WRITE_ENABLE_ALPHA;

【讨论】:

感谢您的更新。我已经尝试了一些东西,包括你的建议,但它似乎没有按预期工作。请参阅上面的描述以获取更多信息。谢谢

以上是关于DirectX 图像纹理四边形在透明的地方显示底层控件颜色的主要内容,如果未能解决你的问题,请参考以下文章

透明四边形上的OpenGL DECAL纹理?

OpenGL GLSL 通过任意形状混合两个纹理

OpenGL核心配置文件不会纹理四边形

OpenGL调整纹理/四边形

使用 SharpDX 在 WPF 中滚动图像时出现生涩动画

使用OpenGL显示图像?