need your opinion / help - to use the Z buffer, or not to use the Z buffer (2D)

Started by
6 comments, last by _the_phantom_ 19 years, 7 months ago
hi everyone, im working on a 2D tile based RPG w/ SDL and OpenGL. anyway, i've recently discovered this wonderfull thing called the Z axis [smile]. i've been wanting to implemented a "layered" effect in my game. that is, i could stack tiles on top of each other, or have the player walk "behind" a building, AND have him be able to walk "in front of" that same building. the only way to do this was to have a layered effect, that is, draw certain tiles over the player, and other tiles under the player. i had 2 choices - the first being i could render the map in 2 passes, that is, Render_Bottom_Layers(); Render_Player(); Render_Top_Layers(); this would give the effect im looking for. the problem is, its slower because i have to render in multiple passses. not only do have to run through my (tightish) drawing loop more then once, but i also have to stick my tiles in multiple vertex arrays. this makes things slower. not only that, but theres other things besides tiles i want to give the layered effect. like free-floating objects, IE, a street light, a building, etc. these are map objects which arent made up of tiles, but are whole images which i draw. so again, i would have to draw these in multiple passes. the second choice, was using the Z buffer. this was awesome!!! this made it VERY easy to put things on different layers - just give things different Z values. i only have to render in one pass, using one vertex arrray. also, its VERY convenient to give things a "layer" value. anyway, theres one problem with using the Z buffer (if you recall the old thread), that is transparency. when 2 objects are transparent and have varying Z values and are rendered on top of each other, the thing which is drawn first will "cover up" the thing drawn last, that is, it will make the second object fail the depth test and not be rendered. glAlphaFunc actually solve's most of the problem, by throwing away pixels which are completely transparent, but this only works with completely transparent objects. so really, it boils down to semi-transparent objects, with varying Z values, rendered one on top of the other. now, im stuck with this problem that im asking for your guys help with. do i get rid of this Z axis idea, and just render in multiple passes (i DONT want to do this if i dont have to), OR, should i stick with the Z axis, and somehow figure out a way to sort semi-transparent objects which have vary Z values? im thinking it will be easier to render in multiple passes, but it will be faster (and more convenient if i figure a way to sort transparent stuff) if i use the Z buffer. also, any suggestions on how to sort transparent objects in a clean way is greatly apreciated. thanks for any help!
FTA, my 2D futuristic action MMORPG
Advertisement
Quote:Original post by graveyard filla
hi everyone,

im working on a 2D tile based RPG w/ SDL and OpenGL. anyway, i've recently discovered this wonderfull thing called the Z axis [smile]. i've been wanting to implemented a "layered" effect in my game. that is, i could stack tiles on top of each other, or have the player walk "behind" a building, AND have him be able to walk "in front of" that same building. the only way to do this was to have a layered effect, that is, draw certain tiles over the player, and other tiles under the player.

i had 2 choices - the first being i could render the map in 2 passes, that is,

Render_Bottom_Layers();
Render_Player();
Render_Top_Layers();

this would give the effect im looking for. the problem is, its slower because i have to render in multiple passses. not only do have to run through my (tightish) drawing loop more then once, but i also have to stick my tiles in multiple vertex arrays. this makes things slower.

not only that, but theres other things besides tiles i want to give the layered effect. like free-floating objects, IE, a street light, a building, etc. these are map objects which arent made up of tiles, but are whole images which i draw. so again, i would have to draw these in multiple passes.

the second choice, was using the Z buffer. this was awesome!!! this made it VERY easy to put things on different layers - just give things different Z values. i only have to render in one pass, using one vertex arrray. also, its VERY convenient to give things a "layer" value.

anyway, theres one problem with using the Z buffer (if you recall the old thread), that is transparency. when 2 objects are transparent and have varying Z values and are rendered on top of each other, the thing which is drawn first will "cover up" the thing drawn last, that is, it will make the second object fail the depth test and not be rendered. glAlphaFunc actually solve's most of the problem, by throwing away pixels which are completely transparent, but this only works with completely transparent objects. so really, it boils down to semi-transparent objects, with varying Z values, rendered one on top of the other.

now, im stuck with this problem that im asking for your guys help with. do i get rid of this Z axis idea, and just render in multiple passes (i DONT want to do this if i dont have to), OR, should i stick with the Z axis, and somehow figure out a way to sort semi-transparent objects which have vary Z values?

im thinking it will be easier to render in multiple passes, but it will be faster (and more convenient if i figure a way to sort transparent stuff) if i use the Z buffer.

also, any suggestions on how to sort transparent objects in a clean way is greatly apreciated. thanks for any help!


I'm sorry, but how the hell can you not render that in one pass?!

/MindWipe

EDIT: You probably means "2 draw loops" or something. 2 render passes is a whole other thing...

"To some its a six-pack, to me it's a support group."
Personaly, I'd use the z-buffer with multiple vertex arrays, fill rate is going to be your killer here, not vertex submission rates.

You need to organise your engine so that it can deal with things correctly however.

First concept;
Layers.
You've made it pretty clear that you are going to have layered data, so first thing is to have the map defined in such a way that the each layer is split up AND that semi-transparent objects on each layer are split away from the solid objects/textures.

Then, I'd draw the solid objects from FRONT to BACK, with z-writes on. This takes care of overdraw, so if something is infront of something on a back layer the back layer is rejected and is never drawn.
Once that has been done its a simple matter of switching z-writes off and rendering your semi-transparent objects from BACK to FRONT. This lets the blending accure properly and with the z-buffer on for comparing will prevent overdraw again where solid objects cover semi-transparent ones (for whatever reason).

As to when to draw the player model, well that depends on if its solid or not, if they are full color with no semi-transparent sections or you are doing alpha testing to remove certain pixels then between the soild and semi-transparent sections would be best.
If they are semi-transparent in any way you'll want to draw them with the correct layer.

All that can be done in one pass, a term you appear to have confused slightly; different passes would be the same geometry with different effects applied. This is a case of drawing different geometery with different effects applied, so its all still one pass.
thanks for your guys replies. sorry about the mix up with the terminology - by passes, yes, i meant loops. IE, i could either draw the entire screen full of tiles at once, OR, i could draw the bottom layered tiles, then draw the player, then draw the top layered tiles. this is what i was considering "2 passses". since i would draw my tiles in 2 swoops, rather then one.

Quote:Original post by _the_phantom_
Personaly, I'd use the z-buffer with multiple vertex arrays, fill rate is going to be your killer here, not vertex submission rates.

im confused... i thought my choices were to either draw with multiple vertex arrays, OR use the Z buffer. if i use the z buffer, i can keep all my tiles in one array, and just draw the whole thing at once. (i think?)

when you say front TO back, what do you mean exactly? you mean things that are closer to the camera TO things that are further from the camera?

more terminology, what do you mean by z-writes ? do you mean disabling / enabling depth testing or something?

now that i think about it more, im starting to lean towards just rendering my tiles / map objects in 2 loops. so far that seems like it will be easier then trying to sort my transparent objects. it would be a shame to not make use of the Z buffer though, since its so convenient, but this transparency thing is a problem.

thanks a lot for anymore help!
FTA, my 2D futuristic action MMORPG
Well, yes you could keep everything in one array and draw everything at once, however its not an either/or situation, you can use both multple arrays with the z-buffer, if you couldnt how do you think other games get on?

By drawing front to back I do indeed mean draw the objects closest to the camera first and then work backwards. So if you had 4 layersm with layer one being closest to the camera and layer 4 being furthest away then you'd draw layer 1, then layer 2, then layer 3 then layer 4.

z-writes is simply that, when the fragments are rendered they are stored as color values with z-depth, with z-writes disabled the z values dont get written, only the color values. Depth testing relies on these z-writes to happen.

The transparence thing isnt such a bigger problem really, you just need to know what objects are semi-transparent and mark them as such (well, marking the textures they use) and then drawing the right layers. Its no more different than you're first method of drawing the bottom layers, player, top layers, infact its basically the same without the player drawing, just reqires a bit of sorting on map load.

Its a bit of extra work but the results should be better and maybe even a bit faster as you are letting the hardware do the majority of the work when it comes to rejecting fragments, instead of the possiblity of massive overdraw which could kill your frame rate.
Quote:Original post by _the_phantom_
Well, yes you could keep everything in one array and draw everything at once, however its not an either/or situation, you can use both multple arrays with the z-buffer, if you couldnt how do you think other games get on?


well, yes, of course... but in my case, i would only need one vertex array (for rendering my tiles) IF i used the Z buffer.

Quote:
z-writes is simply that, when the fragments are rendered they are stored as color values with z-depth, with z-writes disabled the z values dont get written, only the color values. Depth testing relies on these z-writes to happen.


im sorry, but im still very new to this whole OpenGL thing. could you explain maybe what you mean by fragments? also, how would i enable / disable Z - writes?

Quote:
The transparence thing isnt such a bigger problem really, you just need to know what objects are semi-transparent and mark them as such (well, marking the textures they use) and then drawing the right layers. Its no more different than you're first method of drawing the bottom layers, player, top layers, infact its basically the same without the player drawing, just reqires a bit of sorting on map load.


mark the textures they use? why would i do that? i thought it was the geomoetry and the glColor4f() call which would have to be "marked".

Quote:
Its a bit of extra work but the results should be better and maybe even a bit faster as you are letting the hardware do the majority of the work when it comes to rejecting fragments, instead of the possiblity of massive overdraw which could kill your frame rate.


over-draw is when one object is being drawn, but something else is covering it up, so its not seen, correct? if so, i dont really see where this would be a problem. in my map editor, i have an "Eraser" tool which i can use to remove any tiles which aren't visable, anyway. in fact, i cant even picture a situation in my head where over-draw will occur. maybe im mis-understanding what you mean by over-draw.

theres one thing i want to clear up. i dont really plan on allow a tile to have a transparency level. i also dont really plan on making free-floating objects have a transparency level. however, i *would* like to make this a possibility in the future if i wanted to. but for now, really, my main concern here, is things like particle effects, explosion animations, targetting image (bullseye), etc. things like this, will have semi-transparency. my main concern is having these special effects and misc. images vanishing because they fail the depth test because some other semi-transparet object was rendered on top of it, with a varying Z value.

hmmm... now that i think about it. would this be the (very obvious and simple) solution? simply put, any transparent objects, will ALWAYS be drawn at the same Z value. this way, the semi-transparent things could be rendered on top of each other, and there would be no problems with anything failing the depth test, since they share the same Z value, right?

also, since the 2 objects are transparent anyway, they really dont need varying Z values. i mean, how could one thing appear like its behind the other, if they are both semi-transparent and blending togeather, right?

thanks a lot phantom!!!
FTA, my 2D futuristic action MMORPG
oh well, thanks for your help phantom. i guess im going to get rid of the Z axis then, because it will just be safer and easier.
FTA, my 2D futuristic action MMORPG
np, end of the day its upto you, personaly i'd go with a layered z-buffered solution but thats just me :)

To answer you're last couple of questions :

fragments - for all intents and purposes, these are pixels with depth.

glDepthMask() is used to control the writing to the depth buffer.

My marking I was refering to the map editing process. You'd need a way to know which textures/quads should be draw in the transparent layer and which shouldnt.

anyways, good luck with getting it sorted [smile]

This topic is closed to new replies.

Advertisement