[Solved] Drawing primitives and spritebatch

I am attempting to draw my tiled map (using primitives) with my character (using spritebatch) over the top. However, my character always appears under the tiled map or the character appears in part of the map and not another. I would like to draw the character above most of the tiled map layers, but underneath a semi-transparent layer. Note, I am using MG.Extended. Below is my method to draw each:

SpriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, null, _camera.GetViewMatrix());

var projectionMatrix = Matrix.CreateOrthographicOffCenter(0, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, 0, 0f, -1f);

if (layer.Name == “something”)
{
tiledMapEffect.“stuff” = …stuff;
tiledMapEffect.WorldMatrix.Translation = vector3(0,0, 0f);
tiledMapEffect.ProjectionMatrix = projectionMatrix;

GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, model.TrianglesCount);
}
else
Diddo as above except my depth is 1f.

_spriteBatch.Draw(texture, …other stuff…, layerDepth: 0.5f);

SpriteBatch.End();

How do I draw using both primitives and spritebatch and interspersed depths?

You have to draw as you need to. Multiple SpriteBatch.Begin’s and End’s aren’t going to hurt.

  • Draw custom map model
  • Draw map tile layer 1 with SpriteBatch Begin/End
  • Draw another custom map model
  • Draw map tile layer 2 with SpriteBatch Begin/End
  • Draw map tile layer 3 with SpriteBatch Begin/End
  • etc

If you take a look at SpriteBatchItem.cs the depth is written into the Z coordinate. So to mix depths you just need to apply the same/appropriate values to whatever else you draw (assuming you have depth write and test enabled). So make sure your model’s z-coordinates after vertex shader transform fit within the range of depth for the desired layer.

Since Z is being used reasonably you could probably just render everything that goes to the SpriteBatch and everything that doesn’t before/afterwards and let the z-Buffer sort it out for you - your rmileage will vary with things like transparency.


You really shouldn’t be doing other drawing commands inside of SpriteBatch.Begin and SpriteBatch.End. Whatever code you have inside of the Begin/End that isn’t about dealing with the SpriteBatch is going to be brittle as it’ll be working within whatever state the SpriteBatch has used.

Even a tiny bit of refactoring can mess everything up and leave you baffled as to why “working” code has “stopped working” when you do things like that. The graphics device pipeline is just a big state-machine.

Thanks for the input. I can get it to work if I draw my tile layers, then draw my character spritebatch, then draw my tile layer that is goes over everything; but I cannot seem to get it to work with settings my z value of (0, 0.5f, and 1f respectively). Any further help would be appreciated. Thanks.

Got it figured out. An excellent link to drawing with both primitives and spritebatches can be found here: http://xboxforums.create.msdn.com/forums/t/99090.aspx

I’ll also post some code just to help anyone else out:

        Matrix viewMatrix = _camera.GetViewMatrix();

        var projectionMatrix = Matrix.CreateOrthographicOffCenter(0, Game.GraphicsDevice.Viewport.Width, Game.GraphicsDevice.Viewport.Height, 0, 0f, -1f);

        var effect = new AlphaTestEffect(Game.GraphicsDevice);
        effect.Projection = projectionMatrix;
        effect.View = viewMatrix;
        effect.VertexColorEnabled = true;
        _spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone,effect, viewMatrix);
        _entityRenderer.Draw(gameTime);
        _spriteBatch.End();


        Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
        Game.GraphicsDevice.BlendState = BlendState.AlphaBlend;

        Draw all primitives at the end. set the layer depths between 1 and 0.

Here are a few key tips: DepthStencilState must me set in the spritebatch and in the primitives, otherwise it gets set to none. AlphaTestEffect must be used with the spritebatch and just a Basic effect when drawing meshes. I also struggled with GraphicsDevice.Clear. In my case i did not need to specify clearing the dpeth state or the stencil. Simple Clear(Color.Black) fixed many of my issues as well.