Jump to content
  • Advertisement
Sign in to follow this  
dave09cbank

Image texture quad displays underlying controls color where it is transparent

This topic is 724 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi 

 

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

 

[attachment=33122:Capture_map_icon_issue.PNG]

 

 

Yellow Circle image:

[attachment=33124:label-yellow.png]

 

Green circle Image:

[attachment=33123:label-green.png]

 

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   ?

 

Any suggestions or can direct me into the correct direction ?

 

Note: Using Directx11 with ShapDx 

Share this post


Link to post
Share on other sites
Advertisement
I do not set the alpha blend setting at all. Thus I assume by default it is set to be off. I've even tried to set them but still it doesn't work.

Share this post


Link to post
Share on other sites

By default yes, blending is not enabled.  What settings have you tried and what format are the textures you're using?  There are a few steps that you need to do to get it working.

 

  1. Make sure the image format you are using contains an alpha channel.
    • This means using something like DDS, TGA, or PNG image formats which can contain an alpha channel.
    • You can create your own alpha in the pixel shader, but typically the alpha comes from the image.
  2. Make sure the texture format you are creating and loading the image into has an alpha channel.
    • I haven't used SlimDX so I'm not sure if it manages the loading for you, if it does then it should create an alpha format texture if the source image has an alpha channel.
    • Typically (or is it required?), if the texture has no alpha channel, but you sample it expecting to have one, it will return 0.  You'll be sampling for more channels than the texture actually contains, so the device has to make up some value to return, but it probably won't be what you want/expect.
  3. Create a blend state with blending enabled and the proper color/alpha states.
    • Typically this is just src_color: src_alpha, dst_color: inv_src_alpha for standard alpha blending.
  4. Make sure you actually sample/return the alpha in your pixel shader.
    • You could do other things here, return a specific alpha value, return the luminosity of the color as the alpha, return max(color.rgb) as alpha, etc.
Edited by xycsoscyx

Share this post


Link to post
Share on other sites

Since by default blending is not enabled then it should work without giving/showing the issue as per the question asked.

 

 

 

  1. Make sure the image format you are using contains an alpha channel.
    • This means using something like DDS, TGA, or PNG image formats which can contain an alpha channel.
    • You can create your own alpha in the pixel shader, but typically the alpha comes from the image.
  2. Make sure the texture format you are creating and loading the image into has an alpha channel.
    • I haven't used SlimDX so I'm not sure if it manages the loading for you, if it does then it should create an alpha format texture if the source image has an alpha channel.
    • Typically (or is it required?), if the texture has no alpha channel, but you sample it expecting to have one, it will return 0.  You'll be sampling for more channels than the texture actually contains, so the device has to make up some value to return, but it probably won't be what you want/expect.
  3. Create a blend state with blending enabled and the proper color/alpha states.
    • Typically this is just src_color: src_alpha, dst_color: inv_src_alpha for standard alpha blending.
  4. Make sure you actually sample/return the alpha in your pixel shader.
    • You could do other things here, return a specific alpha value, return the luminosity of the color as the alpha, return max(color.rgb) as alpha, etc.
    •  

 

  1. 1.  Using PNG image. I have tried setting the Alpha value in the pixel shader and it displays black where it's meant to be purple. So from my understanding it seems the alpha value is set to 0 in the image.
  2.  Using SharpDx i create the creature from the image data bytes. the texture format is B8G8R8A8_UNorm
  3. I do not set the blending state at this. Do i need to set it ?
  4. Return the alpha of the image itself without making any changes to it.

 

Furthermore, the circular images are drawn on top of the background image.

 

Why would it display the colour of the underlying control and not the background image ?

 

And if i take your suggestion from .4 and return the luminosity of the color as the alpha would that no affect the alpha when i actually need to display the alpha value as it is ?

 

Also will try to set the alpha blending state and see if that helps to resolve the issue.

Thanks.

 

Edit:

I've tried setting the blend state as below:

 m_renderTexture = CreateTexture2D(m_Dx11Device, iWidth, iHeight, BindFlags.RenderTarget | BindFlags.ShaderResource, SharpDX.DXGI.Format.B8G8R8A8_UNorm);

 m_RenderTargetView = new RenderTargetView(m_Dx11Device, this.m_renderTexture);
 m_Dx11Device.ImmediateContext.OutputMerger.SetTargets(m_RenderTargetView);
               
 m_Dx11Device.ImmediateContext.OutputMerger.SetTargets(m_RenderTargetView);

 // code to set the alpha blend state
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.SecondarySourceAlpha;
renderTargetDesc.BlendOperation = BlendOperation.Add;
renderTargetDesc.RenderTargetWriteMask = ColorWriteMaskFlags.All;

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

m_blendState = new BlendState(m_Dx11Device, desc);

blendStateDesc.RenderTarget[0] = renderTargetDesc;

The above still didnt work and my issue still present. 

Edited by dave09cbank

Share this post


Link to post
Share on other sites

Ah, I think I misread a step there, but I'm still not entirely sure on your setup.  Here's a few thoughts/questions.

 

Are you rendering three layers?  The circle (with alpha), on top of a control (purple), on top of the background image?

  • ?If this is the case, then you need to pass the alpha from the circle to the control, then render that over the background with blending enabled.

Are you rendering the circles to the texture, then rendering that over a purple control?  Rereading your post, this seems to be what you are doing?  You're rendering things (the background image and the circles) into a target, then showing that over a purple control?

  • If this is the case then what's happening is that you're just rendering everything as is, all channels.  This means you draw the background image first, then overwrite that with the circle images RGBA values.  Then your final image has the holes in it because it copied the alpha from the circles, so when you display that over the purple, you see through it.

Both cases still seem like you need to enable blending.  In the first case, you need to just draw the image onto the control, then enable blending when drawing the control over the background image.  In the second case, you need to enable blending when drawing the circle over the background image.

Share this post


Link to post
Share on other sites

Thanks for the reply. 

 

I think i'm performing the steps suggested in the 2nd suggestion i.e. 

  1. Draw the background image
  2. Draw the circle images
  3. invalidate the surface (purple control)

 

As suggested iv tried to enable/disable the blending  just before and after drawing the circle images (shown ins steps below)

  1. Draw background image
  2. Enable blending
  3. draw all circular images
  4. Disable blending
  5. Invalidate the texture surface

 

The code used to perform the blending:

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

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

            m_blendState?.Dispose();

            m_blendState = new BlendState(m_Dx11Device, desc);

            desc.RenderTarget[0] = renderTargetDesc;
                       
            if(bEnable)
            {
                m_Dx11Device.ImmediateContext.OutputMerger.SetBlendState(m_blendState, new Color4(0f), -1);
            }
            else
            {
                m_Dx11Device.ImmediateContext.OutputMerger.SetBlendState(null, new Color4(1.0f), -1);
                m_blendState?.Dispose();
            } 
 

Yet it doesn't seem to work and now the circle images aren't visible at all (just black screen) from which i assume either they are transparent completely or not render. However, i believe it not to be the later case.

 

Any further suggestion ?

 

Thanks.

 

NOTE:

The images (background and circular) are being rendered using quad textures.

Edited by dave09cbank

Share this post


Link to post
Share on other sites

I have now spent last few weeks trying to figure out what/where i'm going wrong but had no luck to do so. 

 

Could anyone suggest anything on the above problem ?

Share this post


Link to post
Share on other sites

Have you checked the debug output?  If nothing is rendering (or a black square), then it sounds like something else is happening (SRV not bound anymore?).  For the blending, your order of operations looks correct, though what do you mean by invalidate texture?  I'd try out some different debug output, write .5 to the alpha when drawing the circles, just to check with a fixed value.  If it renders at half opacity there, then the issue would be with your input texture.  Try different things like that, even rendering the squares without a texture at all, just output a fixed color and alpha value, just to make sure that part is working correctly.  If it's a texture issue, you can also try just outputting the alpha to the color, and don't enable blending at all, just to visually see what value you are getting.

Share this post


Link to post
Share on other sites

Thanks for the reply xycsoscyx 

 

I have been trying out different suggestions mentioned by yourself 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

 

 

2. 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 ?

 

 

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!