Jump to content
  • Advertisement
Sign in to follow this  
omnomnom

XNA transparent sprites problem

This topic is 2479 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 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

Share this post


Link to post
Share on other sites
Advertisement
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.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!