SpriteBatch was designed to provide an easy and efficient way to draw 2D sprites. Everything it can do, you can also do yourself by creating vertices and calling the lower level Draw* APIs, so our goal with SpriteBatch was to make the most common operations easier, not to support every obscure corner case.
While testing Game Studio 1.0, we learned that corner cases are common even in simple 2D games! And the SpriteBatch API turned out to be so convenient, it was considerably irritating every time we wanted to do something outside the limited options provided by the SpriteBlendMode enum. We considered adding more state parameters to SpriteBatch.Begin, but our API exposed too many renderstates for that to be practical.
Instead, we added SpriteSortMode.Immediate, which lets you set whatever state you want directly onto the GraphicsDevice. This made many things possible, although not exactly elegant:
- You have to Begin the SpriteBatch in Immediate mode, then set custom state after SpriteBatch.Begin but before the first Draw
- Doesn’t work if you set state before calling Begin
- Doesn’t work if you change state after the first Draw
- Can’t use custom states with any other SpriteSortMode than Immediate
But hey. This was late in the 1.0 development cycle, so we had to do something simple and low risk.
We can do better:
Game Studio 4.0 makes it possible to specify the entire device state with just four state objects. We changed SpriteBatch.Begin to take advantage of this, removing the SpriteBlendMode enum, and instead directly specifying one or more state objects.
|XNA Framework 3.1||XNA Framework 4.0|
null, null, null, null,
- The order of the first two parameters (blend and sort mode) is reversed
- The SpriteBlendMode enum is replaced by built-in BlendState objects
- SpriteBlendMode.AlphaBlend -> BlendState.AlphaBlend
- SpriteBlendMode.Additive -> BlendState.Additive
- SpriteBlendMode.None -> BlendState.Opaque
- SaveStateMode is gone (state objects make this unnecessary)
- See all those nulls in the last overload? Null means "use the default for this state I didn’t bother to specify", but we can use whatever states we like here:
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.Additive, SamplerState.PointWrap, DepthStencilState.DepthRead, RasterizerState.CullNone);
This is not limited to the built-in state objects, so SpriteBatch can now use any custom blend state, sampler state, etc, with any sort mode.