# Nested Sprite Batch and background draw

my code looks something like this:

        graphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(contentLoader.VerticalGradient, tileSafe, null, Color.DarkGreen, 0, Vector2.Zero, SpriteEffects.None, 0.5f);

// snip a lot, including drawing stuff on the sprite batch.

// create a new sprite batch (for snipping)
var initialViewport = InitialBatch.GraphicsDevice.Viewport;
InitialBatch.GraphicsDevice.Viewport = new Viewport(displayRectangle);
var newBatch = new SpriteBatch(InitialBatch.GraphicsDevice);
newBatch.Begin();

// draw stuff on the new batch

newBatch.End();
InitialBatch.GraphicsDevice.Viewport = initialViewport;

// more stuff on the original batch

spriteBatch.End();


My problem is the third line of code I just added. I want to have a "background" on what I'm drawing (so it's not just black). So I draw it first.

Before I added that third line, everything worked great. But when I added it, everything drawn on the new/inner batch doesn't get displayed. If I draw it all on the normal sprite batch, it gets drawn (but doesn't get snipped properly), if I remove the drawing of the new texture, then the inner spritebatch works fine.

Additional things I've tried

I've tried moving the depth of the "background" texture, and when I do, it either makes the background disappear, or it makes the inner sprite batch stuff disappear. I want both.

Is there any way I can get both? Am I making sense? Is this inner sprite batch thing just crazy? I thought I used a standard example to do snipping, but maybe I got lucky and stumbled upon something crazy that just happens to work?

• what do you mean with snipping? And why are you using multiple spritebatches, you should probably just use one and set to immediate mode or some sorting mode :) – Roy T. May 10 '12 at 7:43
• @McKay - Are you aware that creating a new Spritebatch each frame creates unnecessary garbage? – Steve H May 10 '12 at 12:41
• Ah, yes, good call. I'll move the creation to loadcontent or something. – McKay May 10 '12 at 14:14
• regarding snipping: (@RoyT.) What I want to do is create a "Scroll area", where only part of the drawn content appears on screen, And I was instructed (somewhere, I don't recall where) that the creation of a new sprite batch makes that possible. Maybe it's called "scissor" "scissor rectangle"? – McKay May 10 '12 at 14:16

It won't work like you expect it to too, cause you assume your "inner" sprite batch will be drawn "inside" your "outer" spritebatch, but this is not the way SpriteBatch works. Your "inner" SpriteBatch will be finalized when you call End(). Your "outer" SpriteBatch calls End() after your "inner" SpriteBatch so it draws over your "inner" SpriteBatch and you see nothing.

Or another way to see it: There is no concept of an "inner" SpriteBatch as far as i know of. Every SpriteBatch you create inside another SpriteBatch is just that, another new SpriteBatch, could just as well be created "outside". What counts is the order of your End() calls.

This should work for you:

    graphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
spriteBatch.Draw(contentLoader.VerticalGradient, tileSafe, null, Color.DarkGreen, 0, Vector2.Zero, SpriteEffects.None, 0.5f);
spriteBatch.End();

var newBatch = new SpriteBatch(InitialBatch.GraphicsDevice);
newBatch.Begin();
// draw your stuff
newBatch.End();


However you should create your second SpriteBatch in LoadContent(), not in Draw(), as it costs time. Also, as noted in the comments, you could draw everything in one SpriteBatch using various techniques.

• Yeah, I'll move the second sprite batch creation elsewhere. Thanks. – McKay May 10 '12 at 14:15
• It'll take some work to reorder my end calls (because the code is a bit more complicated than my sample), but I'll give that a shot. I think this will work. Thanks. – McKay May 10 '12 at 14:24
• @McKay if that answered your question, i wouldn't mind you marking it as such! – UrbanEsc May 10 '12 at 17:23
• Yeah, it sounded like it worked, hence the comment (and upvote), but until I tested it this evening (I don't have time to work on this project everyday), I wasn't sure it would. Now that it does, you get the question marked as answer. Sorry about the delay. – McKay May 15 '12 at 4:43