DirectX Image texture quad displays underlying controls color where it is transparent
Asked Answered
A

2

0

I'm trying to draw a texture on texture as show in the image below. enter image description here

Yellow circle Image: enter image description here

Green circle Image: enter image description here

As shown in the above image of penguins, i'm trying to render another image as texture which is shown by green and yellow circles. The image is transparent where purple is shown. Purple is color of the underlying control on which the texture is drawn.

The order of rendering is: 1. render penguins 2. Render green circle 3. render yellow circle 4. render green circle

Now I'm not sure as to why i would be seeing the purple for the green/yellow circle images ?

From testing what I've found is that if I don't set the blend factor and use a different image as the overlay image which has an alpha value then it works fine. So it seems there is something going when i use an image which has its alpha value to be 0.

I've been trying to identify the reason behind this for weeks but can't figure it out the reason for it.

Any suggestions or can direct me into the correct direction ?

Note: Using Directx11 with ShapDx

P.S. I've also posted this question on another forum here but having no luck so far.

Edit: Code to enable blendstate after rendering the penguins image which is background

        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;

P.S. Edit: I have been trying out different ways by trying to narrowing it down and i can conclude the blending works but not as expected but have managed to narrow things down.

While trying to render images on Picture in Picture:

Firstly, i have separated all the drawing of quads in a class. using this class i can draw as many objects as required with calling a couple of functions including setting the following on a draw call:

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

Now, from extensive testing and playing around what i have found is:

  1. I have a quad drawing object which draws the background and a separate quad object to draw the flag png. Using this way the png would show the actual controls color.

Now if i enable the AlphaBlending, what i get is just a gray color filling the flag png quad. Also for this i have tried to update the render the rgb colors returned when i sample the texture: ShaderTexture.Sample(Sampler, input.TextureUV); the color returned is black : r=1, g=1, b= 1, a= 1

  1. If i reuse the same quad object that i have used to draw the background image, and then draw the flag png then my background image is drawn underneath the flag png within the quad representing the flag png and my background image is not quad on the bigger quad.

Now from above (finding in point 2.); it seems the blending doesn't work if i draw using a new quad.

Any ideas why this would happen ?

Afghani answered 22/9, 2016 at 10:41 Comment(2)
what are your blend modes for your blendstate object, translucent should be src_alpha + inv_src_alpha ?Agan
@Agan ive added the code which i have used to enable alpha blending. However, that doesn't work.Afghani
A
1

OK I got this to work.

I performed using the following steps:

        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;
Afghani answered 29/9, 2016 at 12:39 Comment(0)
A
0

It is because when you render your circle, the pixel alpha write too, if your final composited image has to be opaque, you can either use a RGBX8 surface, or masked out the alpha channel in the blend state write colormask, and be sure to keep it cleared to white :

renderTargetDesc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL & ~D3D11_COLOR_WRITE_ENABLE_ALPHA;
Agan answered 24/9, 2016 at 15:49 Comment(1)
thanks for the update. i have tried few things including your siuggestion but it doesn't seem to work as expected. Please see description above for more information. ThanksAfghani

© 2022 - 2024 — McMap. All rights reserved.