Calling SpriteBatch.Draw disrupts previsiously drawn texture depth


Currently, I’m drawing all my 3D scene directly in the back buffer. So something like this:


effect.Alpha = 1f;
effect.Projection = camera.Projection;
effect.View = camera.View;
effect.World = camera.World;
foreach (var pass in effect.CurrentTechnique.Passes)
    for (var i = 0; i < _buffers.Length; i++)
        effect.Texture = _buffers[i].Texture2D;
        GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, _buffers[i].VertexCount / 3);

This results in a scene like this:

Now I’m trying create a UI, and for that I want to first draw to a different render target. The end goal is something like this:

var worldTarget = world.Draw();
var uiTarget = ui.Draw();


The problem is, before even starting to draw to different targets, calling SpriteBatch.Draw() messes up the existing scene. So if after the code described in 1 I try to call SpriteBatch.Draw()…

...see first code block...

This results in this:

I have tried drawing text inside the spriteBatch.Draw call, I’ve tried messing with different Begin parameters, I also tried implementing the whole different renderTarget first but the result is always the same, calling spriteBatch.Drawmesses up the scene depth.

This user seems to have had a similar problem (Textures being drawn as if immediate on multiple spritebatch calls.) but he was already using different render targets, which is not my case. Also his solution (creating the secondary render target with the DepthFormat.Depth24Stencil8 option) did not work in my case.

I’m assuming spriteBatch.Draw() is causing some change of the GraphicsDevice state, but I cant figure out what it is or how to fix it.

Any help or hint is appreciated, thanks!

Oh, I see…

It seems I have to draw my 3D scene after calling spriteBatch.Draw and setting the GraphicsDevice to the correct values, so like this:

GraphicsDevice.BlendState = BlendState.AlphaBlend;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
RenderTarget2D worldTarget = world.Draw(gameTime);

_spriteBatch.Draw(worldTarget, ...);

I thought I could draw my 3D scene outside the spriteBatch call into a secondary render target, and only then draw the render target into the backbuffer. Apparently that’s not the case.

Thanks a lot!

Hi @michi, Welcome to the Community!

I know this topic was answered already but I wanted to ask, where can I follow your project? It looks amazing!

Have you joined the MonoGame Discord yet? there is a showcase thread there if you care to post progress there, would love to see this project progress.

Happy Coding!

It’s not really a “project”, I’m just playing around with premade assets to understand how rendering works, there’s nothing really to it.

I’ll check out the discord, thanks for the invite.

1 Like

Ah cool, mind if I ask where you got the assets from?