Skip to main content
GameDev.net gamedev.net
🔒 Locked

XNA transparent sprites problem

Started by omnomnom Mar 4, 2012 at 12:10 AM 0 replies 2.6k views
Original Post
omnomnom
omnomnom
Hi,

I am using XNA to draw a lot of sprites between a SpriteBatch.Begin() and SpriteBatch.End() on top of a background image. I am using pink as a transparency key in the images I am drawing.

Here is an example of the problem I am having. This is what I want. This is how it should look like:
problem2vr.png
I have a blue background then on top of that I draw the large stone sprite. On top of that I draw 5 brown box sprites and one diamond sprite (well it was supposed to be a diamond my mspaint skills weren't quite up to scratch it turns out...). The "diamond" image has pink around and the pink pixels are drawn transparent so you see the stuff already drawn behind.

But this is what actually happens:
problem1d.png

The sprite is overwriting the sprite behind it. The transparency "cuts" through to the background rather than to the stone sprite.

I can understand why this is happening, although I can't put it into words.


The only solution I can find is to call SpriteBatch.Begin() and SpriteBatch.End() for every sprite drawn which seems very wrong for performance. Although I am only drawing a few sprites in this example in only two layers I will potentially be drawing hundreds in dozens of layers. Can I not put them in a single SpriteBatch.Begin() and SpriteBatch.End() and have working masking too?

My pixel shader looks like this:



PsOut TransparentPS(VsOut v)
{
PsOut ret = (PsOut)0;
ret.Color = tex2D(TextureSampler, v.TextureCoords);
//if the pixel is pink then draw it as transparent
if (ret.Color.r > 0.9 && ret.Color.g < 0.1 && ret.Color.b > 0.9)
{
ret.Color.a = 0;
}
ret.Color.rgb *= saturate(xLighting);
return ret;
}


This is what I am doing in terms of order of calls:

SpriteBatch.Begin();
DrawStoneBackground();
DrawFiveBrownBoxes();
DrawDiamond();
SpriteBatch.End()


This is what I have to do to get it to work:

SpriteBatch.Begin();
DrawStoneBackground();
SpriteBatch.End()
SpriteBatch.Begin();
DrawFiveBrownBoxes();
DrawDiamond();
SpriteBatch.End()


It seems that the screen pixels drawn for a sprite in a sprite batch effectively overwrite each other so I have to .End() the batch to get the changes so far "committed". yeah I am not describing this well, but I think I see why it's behaving like this. I just want to know if I am doing something dumb, if there's an easier way to do this...or if there is a way to get it working in one Begin()/End() block really....or do I have to call Begin()/End() for every sprite drawn. Or maybe it's fine and my concerns about performance are nonsense.

Thanks for any help.

Edit: I have looked for solutions on google but the how-to on MSDN for example puts both layers in seperate Begin()/End() blocks:
http://msdn.microsof...studio.20).aspx
omnomnom
omnomnom
So that's typical, after spending an hour cutting the problem down to a simple example, uploading the images and writing this post, I found what the problem is 5 minutes after posting.

There are several mistakes I have made.

1) I didn't give enough details in the example. I thought it was smart to shorten my spriteBatch.Begin call from:

spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.Default, RasterizerState.CullNone)

to just:

spriteBatch.Begin()

But that wasn't smart because...

2) The problem is I am using SpriteSortMode.FrontToBack and should be using SpriteSortMode.BackToFront. Everything works fine with one Begin()/End() block after I make this change.

3) My "transparency pixel shader" is irrelevant. I didn't realize XNA by default treats pink in images as transparent. It's a bizarre coincidence that I first wrote the shader, then made an image, choose pink as a transparency key and when I ran everything I thought it was my shader that was making it work...

sorry for wasting anyone's time.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.