Return of the SpriteBatch: sorting part 3


SpriteSortMode.Texture sorts sprites by texture.

SpriteSortMode.BackToFront and SpriteSortMode.FrontToBack do the obvious thing.

But what is the difference between the Immediate and Deferred sorting modes, and why should you care?

These
modes both draw sprites in the same order that you call Draw, without
any sorting. Performance will be good if you draw lots of sprites using
the same texture in a row, and not so good if each sprite uses a
different texture: see part 1 for the reason why.

In
all the sort modes except Immediate, calling Begin just sets some flags
on the SpriteBatch object. When you call Draw, the sprite is stored in
an internal buffer. All the real work happens when you call End:

  • If using anything other than Deferred sorting mode, sorts the sprite buffer as specified.
  • Sends the sprite buffer on to the graphics card, using as few
    batches as possible (the less times you change texture, the fewer
    batches will be needed).

Because all the work happens in the End call, you can have many
SpriteBatch instances on the go at the same time without any conflicts.
You could even do other things like drawing 3D models at the same time
as you are adding sprites to a SpriteBatch.

SpriteSortMode.Immediate
works quite differently. It sets all the sprite renderstates inside the
Begin call. Each time you call Draw, it checks whether the new sprite
uses the same texture as the previous one. If they are the same, it
just adds the new sprite to the internal buffer. Otherwise it flushes the
existing contents of the buffer to the graphics card, then starts a new
buffer using the new texture.

One implication of this is that
you can only use one SpriteSortMode.Immediate batch at a time. Because
it is setting renderstates and drawing polygons as it goes along, you
will get conflicts if you try to do anything else with the graphics
card (including drawing 3D models) inside an immediate mode SpriteBatch.

Another
more interesting implication is that because SpriteSortMode.Immediate
sets its renderstates inside the Begin call, if you were to change
these renderstates immediately after calling Begin, the sprites will be
drawn using your custom state. You can do many interesting things with
this:

  • Change the alpha blending renderstates to use blend modes other than the standard SpriteBlendMode options.
  • Set the DepthBufferEnable renderstate to enable the hardware depth
    buffer. This can be an interesting way of sorting sprites by their
    layerDepth parameter entirely on the graphics card, allowing you to draw
    overlapping sprites efficiently in texture order but have them show up on
    the screen sorted by depth.
  • Change SamplerStates[0].MinFilter and MagFilter to draw sprites
    with point sampling instead of the default linear filtering.
  • You can use
    the stencil renderstates to do some cool masking and transition
    effects.
  • Best of all: you can set a custom pixel shader, or begin an effect
    that defines a custom pixel shader, to draw sprites using all kinds of
    fancy shading techniques. The sky is really the limit to what is
    possible here (you can’t easily replace the vertex shader, though,
    because we use that as a core part of positioning the sprite polygons).

Comments (2)

  1. Ultrahead says:

    I really like this series of articles.

    Are there any source codes available for the concepts explained in the last 5 bullets (for XNA, I mean)?

  2. cchance says:

    ya how about moving these to video format on the xna site.

Skip to main content