Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In my game, I have a base Note class, and various subclasses of Note. In addition, I have a NoteCollection class which contains a collection of these Note objects and draws them to the screen. Normally, I'd just do something like this in NoteCollection:

public override Draw(GameTime gametime) {
    foreach(Note n in notes)

However, some of these Note subclasses also need to draw 3D primitives in their Draw() methods. I imagine setting vertex buffers in the middle of a SpriteBatch Begin()/End() block isn't a good idea (I've tried it, anyways). What would be nice would be a SpriteBatch.Pause() method that would save the state of the SpriteBatch, and then you could resume drawing your sprites with, say, a SpriteBatch.Resume(). But alas, there's no much methods.

In short, is there any way to go about this? I'd rather not call SpriteBatch.End()/Begin() from each Note.Draw(), as it'd be really slow and I wouldn't necessarily know what parameters the original outside Begin() was called with.

EDIT: Even though I'm using 3D primitives, my game is still in 2D. All of the Z-coordinates of my vertices are 0.

share|improve this question
up vote 2 down vote accepted

What I would do is create 2 draw lists (List<IDrawable> or better yet, create your own IDraw interface which includes a CullTest(Camera camera) method and a BoundingBox parameter). Then add all the drawprimitives notes into one drawlist and the spritebatch calls in the other list. If you are mixing drawprimitives and spritebatch draw calls inside the note.Draw() methods you should break it up into 2 calls (note.DrawSpriteBatch() and note.DrawPrimitives()). Then I would depth sort the drawprimitives list from closest to furthest away from the camera. After that you can draw both lists. This way you are using only one spritebatch. This is much cheaper than creating a new spritebatch for every node since each spritebatch.Start() sets a whole slew of renderstates. Also, you are reducing the drawprimitives overdraw from drawing distant occluded objects before the objects in front of them (why make the pixel shader shade pixels which are not visible?).

If you do roll your own IDraw interface you can do something like this:

public interface IDraw : ICullable, IEntity
    void DrawPrimitives(DrawState state);
    void DrawSpriteBatch(DrawState state); 

public interface IEntity:
    BoundingBox AABB { get; }
    Vector3 position { get; set; }

public interface ICullable
    bool CullTest(ICamera camera);

//this is useful for being able to switch camera types without 
//changing any code which relies on the camera class
public interface ICamera 
    BoundingFrustum boundingfrustum { get; }
    //and anything else common between your camera classes: 
    //fov, aspect, far, near, position, target...

public class DrawState
    //Elapsed time, Current camera, Current shader
    //anything else that you are sharing between draw calls
share|improve this answer
I'm not quite sure I'm following you. I've never messed with anything involving the camera, since my game is 2D (I'm drawing the "3D" primitives all with Z-coordinate == 0). I had been thinking I'd need to have a DrawPrimitives() and DrawSprites() method in the base Note class, but I'm also not sure what depth sorting entails or how to do it. – ThatsGobbles Oct 17 '10 at 18:38
I was not aware that you were working with 2d. In that case you don't really need to worry about sorting the primitives by depth or distance from the camera/eye. The reason for depth sorting will become clear to you if you ever attempt to draw transparent objects in 3d space. You can read more about it here:… Regardless, you should still create 2 draw lists, one for drawing primitives and one for spritebatch. – zfedoran Oct 17 '10 at 21:13

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.