Preserve depth across multiple Spritebatches

Hi folks!
Does anyone have an idea of how to preserve depth across multiple sprite batches?
like:
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, null, Camera.GetViewTransformationMatrix());


spritebatch.end();
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, null, Camera.GetViewTransformationMatrix());

spritebatch.end();

and so on, Iam trying to apply shaders to individual sprites btw.

In another way, if I can prevent the depth buffer from resetting when spritebatch.end() is called
this would solve my case.

Nope. SpriteBatch doesnt use depth buffer so you must sort sprites yourself before rendering them (when using multiple Begin()/End().

edit: I was wrong, spritebatch can use depth buffer too.

1 Like

I would have thought the default behavior in spriteBatch would be to apply the depth value as the z value of the vertex being sent to shader.

I remember a while back I did occlusion query with spritebatch but not sure what I did. I do recall that the depth values were 0 to -1 instead of 0 to 1 (it was XNA - not 100% sure if exactly the same behavior?). If End is simply sorting by depth and writing to a single depth, then that’s no good for multiple batches.

Another thing you could do is use my QuadBatch which works in a very similar way (but textures are expected to be sprite-sheets assigned in Begin-End pairs). It’s fast, preserves depth, and shader overrides.You can cross Begin-End pairs many times because it’s setting individual z values for vertices (if changing Z value for each draw). I should probably put it up on github. I have older versions out there already - like on my website

(see source code below and in the RAR, it’s QuadBatch which has it’s own default shader like spritebatch]:


(I’ve improved it a bit since then)
[Probably when I find time I’ll put up the slightly improved version on Github]
1 Like

I don’t know if that will affect performance much or not, but I think it’s a valid solution, thank you!

Just for curiosity, can you tell me how you managed to preserve depth between multiple begin and end in your implementation?

Weird thing is I checked spriteBatch’s source and it sets z for the vertex as the depth and I don’t see anywhere where the depth is cleared and End shouldn’t effect it - so I’m not sure what’s going on with that. Strange.

The way I was doing it in my own version (QuadBatch), was pretty similar - to set the actual depth value of the vertices so when it calls End, everything is drawn to actual depths (except no sorting)… which other than the sorting option (and camera setup), there’s not really any difference I noticed and those shouldn’t effect it so that’s really curious.

I’m wondering if the results are same with immediate sort mode? I’m just thinking maybe something’s going on with device state changes… altho that seems unlikely to cause the issue too.
Also wondering what happens if you use depths ranging between 0 and -1?
Are you using depth16 or 24 (preferably not none - lol )?
Also are you clearing the depth buffer at the top of each frame? Also worth mentioning that transparent pixels will still have depth assigned unless setup right. It’ll never write pixels behind pixels that are closer even though they’re see-thru. That would require setting a color key and enabling it.
I’m not sure how much of this stuff you know already or tried already :wink:

1 Like

When I use one sprite batch, ordering works fine, but I can’t apply shaders to individual entities, but if use multiple sprite batches, the reverse happens😥, you can check the spritebatch.begin that I use in the post, I don’t think I did anything regarding the depth buffer (since I have never dealt with it)

I found this line in the end() function in spritebatch class:
GL.Disable(All.DepthTest);

Is this relevant to the depth of images we are talking about?

1 Like

GL.Disable(All.DepthTest);

Oh! - well that would probably do it. That’s odd, since I know they’re trying to make it work exactly the same as XNA but I coulda swore XNA did retain depth. I could be wrong - someone please correct me if I am wrong (I’m probably wrong). ;p

I suppose one could remake a version of this spritebatch without the depth disable in End. In the mean time, my Quadbatch should do the trick. It would be great if there was an additional End overload that allowed us to keep depth enabled after drawing.

Another thing that might work is to use immediate and drawing at depth (it won’t sort by depth but depth-testing should take care of drawing it so closest pixels show up). Immediate (no sort and device states setup ahead of time) – you should be able to switch effects part way through so you won’t need multiple begin-ends.
So if you use:

SpriteSortMode.Immediate
and thus won’t need to pass the effect in begin but for each effect (just before drawing) you’d do this:
effect_one.CurrentTechnique.Passes[0].Apply();
// Draw stuff here
effect_two.CurrentTechnique.Passes[0].Apply();
// Draw other stuff here

Maybe you could try that out? :wink: