How can I remove Magic Pink from an image at runtime using GraphicsDevice?

In XNA 4.0, I want to load all my textures at runtime, which means I will not be able to take advantage of the content processor. (This is fine because it would allow people to change graphics and other elements without having to have XNA installed to compile them into .xnb)

Suppose that I can't (or don't want to) use premultiplied alpha on my images, and instead rely on the classic magic pink (255, 0, 255) method:

How can I turn it into a Texture2D object and convert the pink to be transparent using GraphicsDevice? It is trivial to iterate the data with GetData() and SetData(), but this uses the processor, rather than the graphics card.

• Funny; I have never heard/read it referred to as Magic Pink! The standard on the Nintendo DS I worked on was to specify the first colour in the colour map that would be transparent; this would allow artists to be able to use the 0xFF00FF if they felt they needed it. – Vaillancourt Mar 21 '15 at 21:20
• I think I picked up the term from Gamer Maker several years ago. Anyways, I can indeed compared against if (myTexture.PackedValue == 0xFFFF00FF) (BGRA) and replace it with Color.Transparent (or 0x00000000), but this approach relies on using the CPU, rather than the GPU. Where is the color map located, within the .png itself or the Texture2D object? – Kyle Baran Mar 21 '15 at 21:24
• So why exactly you have to do the color conversion on run-time and you can't use Photoshop to convert the color to transparent ? – dimitris93 Mar 21 '15 at 21:29
• Stubbornness, mostly. It can be difficult to tell what's going on for sprites that are only a few pixels wide when transparency becomes involved, and when viewing them in a file viewer, it can be hard to see where the image bounds are. – Kyle Baran Mar 21 '15 at 21:32
• @VaughanHilts "because it would allow people to change graphics and other elements without having to have XNA installed" – Kroltan Mar 22 '15 at 1:43

I would imagine a custom pixel Shader for the SpriteBatch would be the fastest method here.

Using something like this:

// WARNING! UNTESTED CODE FOLLOWS
void SpriteVertexShader(inout float4 color : COLOR0, inout float2 texCoord : TEXCOORD0,
inout float4 position : POSITION0)
{
if (color == float4(1, 1, 0, 1)
color = float4(0, 0, 0, 0)
}


In a custom effect passed to your SpriteBatches Begin() method, it should make every pixel with an ARGB value of OxFFFF00FF transparent while keeping any pixel with a different color the same.

I haven't done much work with 2d shaders apart from Post Processing effects, so I'm not exactly sure what values you'll need to pass to Begin() to get transparency working correctly.

• I figured a shader would be the most direct method... I looked at various SpriteBatch settings (stencil, raster options) but they didn't seem to give much leeway on the color options. – Kyle Baran Mar 21 '15 at 21:54