SpriteBatch sorting part 2

Continuing from yesterday...

Let's consider a practical example of how to sort sprites for good performance. Imagine I am making a game called Super Dromedary Racer Extreme, which requires a top down view of a piece of desert. My graphical elements are:

  • The ground is a tilemap containing various arrangements of sand dunes.
  • I have several types of object in the world: palm trees, flags
    marking the start and finish lines, spectators, a couple of passing
    kangaroos, and of course the dromedaries themselves.
  • I want the dromedaries to kick up huge clouds of dust, which I'm
    going to implement as a large number of alpha blended particle sprites
    that gradually increase in size and rise upwards as they fade away.

The ground obviously needs to be drawn first, so that it will appear
below all the other objects. When I loop over my tile map, I will be
drawing the different sand dune tiles in a basically random order, but
there is a useful trick that can avoid the need for me to bother
sorting these sprites. Rather than using a different texture for each
type of tile, I can arrange all the possible tile designs into
different areas of a single larger texture. In my SpriteBatch.Draw call
I can then use the sourceRectangle parameter to specify which part of
that large texture should be used for each tile. Since all my ground
sprites are now using the same texture, I can draw them without sorting
and still get perfect batching, using the fastest possible immediate
sort mode:

    spriteBatch.Begin(SpriteBlendMode.Opaque, SpriteSortMode.Immediate, SaveStateMode.None);

// draw all the ground tiles


Now to draw my game objects. Ideally I would like to be able to do this with some code along the lines of:

    foreach (GameEntity dude in gameEntities)
spriteBatch.Draw(dude.Texture, dude.Position, Color.White);

if (dude.HasDustTrail)
foreach (DustParticle particle in dude.DustTrail)
spriteBatch.Draw(dustTexture, particle.Position, null,
Color.White, 0, Vector2.Zero, 1,
SpriteEffects.None, particle.LayerDepth);

But there are problems with this approach. Because my game entities
are not necessarily sorted by their texture, it will cause poor batch
performance. Worse, it won't even render the correct thing! Because my
alpha blended dust particles are overlapping each other (and could even
be merging with particles from a different dust cloud if several
dromedaries are racing near each other) these will need to be sorted by
depth to get a correct result. It seems impossible to get this right: I
need to sort by texture to get good performance, but also by depth to
get correct alpha blending, and I can't sort by two different
things at the same time! Whatever is a poor graphics coder to do?

I could draw all the entity sprites first using
SpriteSortMode.Texture, then end that SpriteBatch and start a new one
using SpriteSortMode.BackToFront for drawing the dust particles. But
then I would have to loop over all my entity objects twice, which seems

The solution is actually very simple:

    spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Texture, SaveStateMode.None);
dustSprites.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);

foreach (GameEntity dude in gameEntities)
spriteBatch.Draw(dude.Texture, dude.Position, Color.White);

if (dude.HasDustTrail)
foreach (DustParticle particle in dude.DustTrail)
dustSprites.Draw(dustTexture, particle.Position, null,
Color.White, 0, Vector2.Zero, 1,
SpriteEffects.None, particle.LayerDepth);


This relies on the fact that as long as you aren't using
SpriteSortMode.Immediate, SpriteBatch doesn't actually do any drawing
until you call the End method. That means you can begin several
overlapping batches with different settings, draw sprites in any order
using any combination of the batch instances, and control what order
the entire contents of each batch get drawn by the ordering of your End

The code is simple, the sorting gives correct alpha blending results, and the batching gives good performance. Hurrah!

Of course, this only works because all the dust particles are using
the same texture. If we had several different kinds of dust, sorting
these by depth would leave the textures in a random order and thus
cause poor batching performance. In that case we could use the same
trick as for the ground tiles: arrange all the possible dust particles
onto a single larger texture, so we can sort the particles however we
like and still avoid having to switch textures too often.

Comments (10)

  1. kreca says:

    What is the reason to


    be called before

    dustSprites.End(); ?

    Or does the order of placing the ends not matter?

    I didnt find any information on when to use the end() calls if using serveral sprite batches.


  2. ShawnHargreaves says:

    The order of the End calls controls which order the whole contents of one batch will be drawn relative to the other batch, since this is the call that actually sends the sprites to the graphics card. The dust should appear over the top of the solid object sprites, so we End the object batch first, then the dust second.

  3. kreca says:

    Ah thanks for the answer.

    Now I understand that the placement of the begin call has nothing to do with this (unless it’s in immediate mode). Thanks!

  4. MDB says:


    What happens when one use an effect instead of a spriteBatch ? Because the begin() method that takes 3 arguments doesn’t exist … and I’m having troubles to draw my objects correctly (it’s flickering) . In fact, I have some objects overlapping others …. and I couldn’t solve the issue … Thanks in advance

  5. ShawnHargreaves says:

    MDB: afraid I don’t really understand your question. This article is talking about SpriteBatch sorting, which doesn’t apply when rendering your own geometry not through SpriteBatch. If you aren’t using SpriteBatch, it’s up to you to implement whatever other sorting method you like.

    btw. I would generally recommend the forums on creators.xna.com for technical support – blog post comments aren’t really the best place for a back and forth conversation!

  6. Siyfion says:

    I thought that in DirectX you could specify a combination of both D3DXSPRITE_SORT_DEPTH_BACKTOFRONT and D3DXSPRITE_SORT_TEXTURE, so that it would sort the textures first by layer depth and then by texture. Is this not possible in XNA without doing it in the way you have shown?

    Problem being is that I can’t see how I could use that method for a large-scale 2D game. For example lets say I have a CharacterBar class, which draws its own background, then a bar representing health (mana, etc..) and then the numeric values of the bar ontop of that.

    The way I currently do it is by giving the CharacterBar class a layer depth to draw at, and then it goes and adds a tiny amount onto that at which to draw the background, then a bit less to draw the bar, etc..

    But say I have 3 identical bars, that all use the same textures, 2 of which are at the same "base" layer depth, really I would like to draw the two backgrounds, then the two bars, then the two sets of numbers and then followed by the other (entire) bar at the different layer depth. But the SpriteBatch used for all of them is the same.

  7. ShawnHargreaves says:

    Most of the time, it’s best to just draw your sprites in the order you want them to appear with no automatic sorting at all.

    Automatic sorting is always going to be slower than just doing things in the right order in the first place, so you should only use this in complex dynamic situations where a fixed draw order is for some reason not possible.

  8. Steph says:

    Do you know the rule when you draw 2sprites at the same position and same zdepth?

    I had experienced drawing 2 sets of 2sprites, with same zdepth. The first set on the left of the screen, the second set on the right. But in the left set the 1st sprite was below the 2nd and with the 2nd set it was the contrary.

  9. ShawnHargreaves says:

    Steph: our sort algorithm is not stable, so if you ask it to sort two sprites with identical depth values, their output order is basically random.

    If you care what order the sprites are sorted in, you need to give each one a different depth value.

  10. XNA newb says:

    I hope I get a response

    I have a camera class associated with the spriteBatch class.  I want to implement a UI but I don't want it to zoom in and out.  Could I implement in a separate spritebatch.

Skip to main content