How to use the z-buffer?
kovarex

Hello,
I just upgraded to new allegro, and I would like to use the z-buffer, so I can draw the isometric projection objects in any order I want (ordered by atlases).

I would expect the allegro to have function like al_draw_bitmap_with_z_buffer, that would just take one float defining the "height" of the bitmap, but I can't see anything like that there, only some al_clear_depth_buffer function, that I don't really understand.

The ex_depth_mask seems to be doing something far more complicated than this.

Could you advice me how to do this? It should be quite simple shouldn't it?

Edit: When I tried to set the option ALLEGRO_FLOAT_DEPTH, the render became 5 times slower

Arthur Kalliokoski

The z buffer is normally used to allow proper ordering in 3D scenes, and it's used by drawing with 3D vertices (x, y, z). You can still use isometric perspective, but you need to use a z component to make the z buffer work properly.

[EDIT]

I'd think it'd be easier to make a struct or class with two members, one is an int to the desired order in the hierarchy, and the other is a pointer to the object to be drawn. Then you'd simply sort these structs using the int as the key, and draw the items (in proper order in the list) via the pointers.

Thomas Fjellstrom

I'd think it'd be easier to make a struct or class with two members, one is an int to the desired order in the hierarchy, and the other is a pointer to the object to be drawn. Then you'd simply sort these structs using the int as the key, and draw the items (in proper order in the list) via the pointers.

That doesn't work so well when you want to sort drawing by the atlas the item's sprites are contained in.

Arthur Kalliokoski

Ok, so have the pointer point to a RECT struct with the texture coordinates.

Thomas Fjellstrom

Ok, so have the pointer point to a RECT struct with the texture coordinates.

Now how do you handle depth? ;) if you're drawing in order of the item's atlas, things won't be layered properly (without a depth buffer or something).

Arthur Kalliokoski

Now how do you handle depth? ;) if you're drawing in order of the item's atlas, things won't be layered properly (without a depth buffer or something).

I haven't used the A5 primitives, or the "A5" way of doing things, but with my OGL GUI I simply disable depth testing and whatever's drawn last overwrites anything that was there first.

Thomas Fjellstrom

I haven't used the A5 primitives, or the "A5" way of doing things, but with my OGL GUI I simply disable depth testing and whatever's drawn last overwrites anything that was there first.

But you can't draw in FIFO order when you're not sorting by z-order. The sprites will be drawn in some order depending on which atlas they are in. In some cases there could be things drawn in the wrong order.

Arthur Kalliokoski

The sprites will be drawn in some order depending on which atlas they are in.

You mean the A5 primitives draw all textures from one sheet before moving on to the next? Half the time using automatic stuff to "make it easy" works against you. (think 'Make Game' button here) I'm content with binding a texture when I need it, thank you very much.

Thomas Fjellstrom

You mean the A5 primitives draw all textures from one sheet before moving on to the next?

No, but he is doing that. using an atlas can greatly speed up drawing.

kovarex

Yes, as I discussed somewhere else, the motivation to use z-buffer is to be able to draw isometric quickly when resources are divided in more atlases, in other words, to be able to switch to every atlas only once.

If I use z-buffer I don't have to order the drawing according to the projection (as I do now), but rather by it's atlas.

But, if the Z-BUFFER usage slows down the render 5 times or more as I experience, it hardly beats those savings.

Thomas Fjellstrom

I'm not sure ALLEGRO_FLOAT_DEPTH is the right option? Might be better to not set that, or set it to false. I don't think you want a floating point depth buffer at all. Integer should be fine. The ALLEGRO_DEPTH_SIZE option should be what you want.

kovarex

Thanks for the advice.
I tried the integer depth, and the max I was able to set and start the application was 24 (found by trial and error).

If I use 4 bits for the game layers, I'm left with 20 bits to sort out the isometry, 2^20 = 1 048 576
If I want the resolution 2560X1600 to be playable I might end up with 4096000 pixels, this would leave me with 1 z-buffer value for 2X2 pixel area, it is good enough.

Now I just have to find out how to use the z-buffer :)

Arthur Kalliokoski
kovarex said:

If I want the resolution 2560X1600 to be playable I might end up with 4096000 pixels, this would leave me with 1 z-buffer value for 2X2 pixel area, it is good enough.

The 24 bits are the depth for each pixel, i.e. you can have 16 million different objects sorted per pixel. You still need to use a 3D vertex to specify the depth.

kovarex

Yes, I understand, that 24 bits are for each pixel, but I if I want the object to overlap other objects correctly, they have to have different values, thats why I have to divide possible values.

I feel like I'm repeating all the time, I just still don't feel being understood, so I will ilustrate it with picture:

On the picture, the left side has bad drawing order, the right has good one, I need to achieve the result on the right even when I draw the top tree first.

I imagine the z-buffer as 2^24 layers and I can choose the layer to draw to, is it correct?

Arthur Kalliokoski

How do you know in the first place which one is further away? Just use the distance in the z component of your 3D vertex. You don't have to worry about "order" then. That's the purpose and proper usage of the z buffer.

kovarex

Yes, that is what I'm trying to achive! I still have to worry about the order, as I order by atlasses to optimise speed.

So we finally agreed that what I want is correct, but I still don't know HOW, I don't see any vertex in allegro, I just need the simplest example possible for drawing two overlaping sprites in one order, but seing the result in the opposite, I can handle the rest.

Elias

You need to use al_draw_prim to set the z value of what you are drawing.

Not sure you can get 2^24 layers. I believe the values are always normalized to 0...1 by opengl/directx. But all Allegro does is enable the opengl/direct render state. If someone figures out how it works we can add it to the documentation.

Arthur Kalliokoski

I'm working on a little OpenGL example right now.

[EDIT]

Well I can't even get something other than a black screen, trying to do too many things for the first time all at once. I'm going back to my xlib stuff.

l j

I'm wondering about the exact same thing.

I was also thinking about ordering by atlas and then let the GPU handle the z-ordering.

Arthur Kalliokoski

I fiddled with it some more, it seems to work except the 32 separate textures aren't transparent (obscures quite a bit). You need to supply your own "DejaVuSans.ttf" or change the name on line 26. It's here.

Maybe somebody who knows what they're doing can fix it so the backgrounds of the bitmaps are transparent.

[EDIT]

OTOH, some of the more distant bitmaps seem to be transparent, look closely at the bluish '28'. I don't know why the nearest ones seem to be opaque.

{"name":"606105","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/5\/55e94ae2c4ca7e0a0270dc330915d7ba.png","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/5\/55e94ae2c4ca7e0a0270dc330915d7ba"}606105

Elias

If you can make it work with al-draw-prim and al-set-render-state instead of opengl calls we could maybe include it as another example. ex-depth-mask only uses the z buffer as a boolean mask so doesn't really show what you can use it for.

Arthur Kalliokoski

I forgot that transparency needs to be sorted from most distant to nearest, which probably explains the opaqueness for some parts of the image. If that's the case, the OP is back to his original problem again, isn't he?

[EDIT]

Well that's not the problem either, I sorted structs with the x,y,z,texnum and it still showed artifacts either way the sort order went, although the 2000 numbers displayed in each image were quite different. It did still maintain 60 fps though.

[EDIT2]

I started a new program from scratch with a visible background and three sprites. unsorted_sprites.c shows what happens if you don't sort by depth, and sorted_sprites.c does it right.

I'd have to experiment quite a bit more to get al-draw-prim and al-set-render-state etc. working correctly.

Thread #610329. Printed from Allegro.cc