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

匿名 (未验证) 提交于 2019-12-03 08:33:39

问题:

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

Yellow circle Image:

Green circle Image:

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 ?

回答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;


回答2:

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;


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!