Drawing a Texture2D with a transparent background

Hi there,

I’ve a texture with the background color in black.

I need to draw it using SpriteBatch.Draw() but I don’t wanna it to draw the black color.

I’ve tried changing the Processor/ColorKeyColor in the MonoGame Pipeline tool but it’s read-only.

What can I do?

Thank you.

Check out the content pipeline tool, properties of the texture/image file. Should be some thing about color key.

Just tried checking it out and reading the community, it seems you cannot edit the color key color (it is Magenta by default?) so you are stuck with that?

Does anyone know why it can’t be edited?

And what about pixels that are also black, but not part of the background? Sounds like to me that you should change the image to add transparency to it and delete the background (whatever color it has), then reload the image into your project and use it the usual way.

The ColorKeyColor property is not read-only and can be edited. It is magenta by default, but it can be changed.

How? It is greyed out.

Does it have to be done in code?

Just tried it in the older MonoGame release. For some reason it is greyed out in the Pipeline tool, but it shouldn’t have been. In the latest code it is editable, and it can be edited directly in the .mgcb file. Add the following line

/processorParam:ColorKeyColor=0,0,0,255

immediately after the /processor:TextureProcessor line.

Forgot it was a text file!

I must agree with Kuz in the end that creating transparent images in the first place is the best option.

It is magenta because usually it is rare to have this color in real life and in a texture too. But if you need this color on sprites it can be changed. But makong you sprite with an alpha channel will be your best bet in order to avoid scratching your head later in development.

So you want only the black transparent? No fading out? Just the black gone?

Ok I can write a shader for you.

Texture2D ScreenTexture;
 
sampler TextureSampler = sampler_state
{
    Texture = <ScreenTexture>; 
};
 
//Note: Color1 not needed.
float4 PixelShaderFunction(float4 pos : SV_POSITION, float4 color1 : COLOR0, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
    float4 color = ScreenTexture.Sample(TextureSampler, texCoord.xy);
    if(color.rgb == float3(0,0,0))
   {
   clip(-1);
   }
 
   return color;
}
 
technique PassThrough
{
    pass Pass1
    {
        PixelShader = compile ps_4_0 PixelShaderFunction();
    }
}

You need to save this file as yourshadername.fx and load it in your content pipeline.

Load the effect file in your game like this:

_myShaderEffect = content.Load<Effect>("yourshadername");

Later you need to use your spritebatch and assign the effect.

_spriteBatch.Begin(SpriteSortMode.FrontToBack, null, null, null, null, _myShaderEffect);

_spriteBatch.Draw(.... your stuff here)

_spriteBatch.End();

EDIT: Actually to check the color being black maybe doing something like dot(color, float3(1,1,1))==0) might be better I guess

Hi KuzDeveloper,

I understand your point but that image don’t have black pixels to draw so I don’t have to worry about it.

Thank you for the recommendation about changing to transparency.

Hi kosmonautgames,

I think that creating a pixel shader is too much for what I need.

Hi KonajuGames,

I’m using the last version of MonoGame v3.5.1 and like I said in the original post the ColorKeyColor is greyed.

I’ll install the previous version v3.5 or v3.4 and check if I can modify the ColorKeyColor property because in my scenario I think it’s the best choice and the faster one.

Thank you.

You could also modify the textures to change the needed black into magenta.

Yep like alkher said,
Since i got a ton of this color manipulation stuff here you go the top two i just scribble out.
You can basically one line it after you load it.

transparentBg2D = ChangeBlackToTransparent(graphics.GraphicsDevice, bg2D, 1);

.

    public Texture2D ChangeColorToTransparent(GraphicsDevice gd, Texture2D t, Color c)
    {
        Color[] data = ColorArrayFromTexture(gd, t);
        for (int i = 0; i < t.Width * t.Height; i++)
        {
            if (data[i].R == c.R && data[i].G == c.G && data[i].B == c.B) { data[i].A = 0; }
        }
        return TextureFromColorAry(gd,data,t.Width,t.Height);
    }
    public Texture2D ChangeBlackToTransparent(GraphicsDevice gd, Texture2D t, int blackthreashold)
    {
        int n = blackthreashold;
        Color[] data = ColorArrayFromTexture(gd, t);
        for (int i = 0; i < t.Width * t.Height; i++)
        {
            if (data[i].R < n && data[i].G < n && data[i].B < n) { data[i].A = 0; }
        }
        return TextureFromColorAry(gd, data, t.Width, t.Height);
    }
    public Color[] ColorArrayFromTexture(GraphicsDevice gd, Texture2D t)
    {
        Color[] data = new Color[t.Width * t.Height];
        t.GetData<Color>(data);
        return data;
    }
    public Texture2D TextureFromColorAry(GraphicsDevice gd, Color[] data, int width, int height)
    {
        Texture2D tex = new Texture2D(gd, width, height);
        tex.SetData<Color>(data);
        return tex;
    }

You can of course make your own like color to color or whatever.
You can then save it back as a actual texture on disk using a stream.

    public bool SaveTexture(Texture2D t, string fullfilepath)
    {
        FileStream f = new FileStream(fullfilepath, FileMode.Create);
        t.SaveAsPng(f, Width, Height);
        f.Close();
        return true;
    }

Hi guys,

Thank you for all the suggestions!

Yes, I’ll change the black color to magenta. In case I need the magenta then I’ll use transparency.

I hope the developer fix this.

Thank you.