making 2D functions observe a Z-buffer
Eric Love

I mentioned this before in the Allegro 5/6 thread, but here I am again. It would be really handy if you could have a z-buffer which the 2D drawing functions were to observe.

Having looked at the Allegro drawing code, I can see that it would be possible, but require a lot of hacking around, with quite a loss in speed.

One method would be to use the ZBUFFER in the same way as the 3D functions can. The code there has a lot of IFs around each PUT_PIXEL and the same method could be carried into the 2D drawing. Another possibility is to use a higher colour depth than the number of colours you're using, so Z-drawing would be faster than translucent drawing.

Has anyone done something like this? Does anyone have any good ideas?

Bob

Well, considering that the 3D polygon routines are going to be spun off from Allegro, and probably end up as an add-on, I don't see why supporting arbitrary zbuffer reads/writes is of any benefit to Allegro at all. If you really need that functionality, then have a look at OpenGL / AllegroGL.

topaz22

another alternative is to sort your sprites to draw in z,y,x order, so you layer em on top of each other (assuming double buffering)...

z-buffering is nice if you have a lot of sprites moving around and you want to have some in front of some others and behind others..

i did some hacking around with using the allegro z-buf stuff (which is just a 32-bit bitmap, storing a 1/float, i think, it was about a year ago), and the performance wasn't too bad actually..

(looking at comments in my old code)

// so, to read out of the zbuf...
 ((long*)zbuf_alleg->line[y])[x];

  union {
    float zf;
    long zi;
  } _zbuf_clip;
                  
// so to get the z value out......... ( the z value stored is actually 1/z )

    _zbuf_clip.zi = ((long*)zbuf_alleg->line[pt16->y-extra_height2])[ pt16->x ];
    zval =  (u16) ( 1/_zbuf_clip.zf) ;
 
clear_zbuffer (zbuf_alleg, clip_far_z);     // 24000 

the other routines that i had were a tad messy, because i was drawing masked, i had to color convert 8 bit as well as check the z-buf, onto a 16 bit screen, and i was scaling, so i merged it into one x/y loop, instead of several

Matt Smith

I doubt that checking a z-buffer would save enough time to justify it over the painters algorithm (back to front). Make a list of sprites to be drawn each frame with z-values and then sort the list with qsort.

white_door

well you could easily sort the sprites by have an array of lists with one list for each possible y that a sprite can be draw at (and still be visible).. this would be both faster and easier to do.

spellcaster

Ok, so when would I want to use a z-buffer?
Normally if using sorted sprites is not really an option, say if your screen consits of a pre-rendered environment. So you might only have a pre-calculated to which your sprites should conform.

I never used the allegro 3d routines, but can't you use a textured quad? I guess the 3d poly routines will use the z-buffer...

Eric Love

Perhaps I posted in the wrong forum for this, because I was more wondering whether anyone had done it rather than requesting functions like this be put in Allegro, although it would be handy in the library, and it does involve hacking the Allegro code.

I tried implementing on Thursday without success. I was trying using 16-bit colour where the upper byte is the Z value.
The main thing I thought I would need to do (heavily simplified) was changing the PUT_PIXEL macros which cgfx.c uses from *p = c to if (c > *p) *p = c and change the MASK macros. The other thing you would need would be functions which operate on the upper byte of a sprite, like painting it's z-value. Normally this would be to a constant z, making it a fast operation, although there would also be the possiblilty of some parts being further forward. I was unsuccessful because I was unable to trace into putpixel with a debugger.

Currently my engine runs through each objects draw method, which may add drawing instructions with a z value to a sorted list of such instructions. After going through all the objects (there's a complicated intermediate step, but never mind), it goes though the list (a tree, actually) and executes them all. Because I'm using a variety of sprite and primitive functions, the code for executing these is increased for every drawing function I make available. Of course if my scripting system was working I could just add compiled scripts to do that. A 2D z-buffer would be an easier but slower way to solve the problem.

Using the 3D functions (like quad3d with texture) would be a lot slower than the methods I was attempting, because there are a lot of multiplications, etc which a 1:1 sprite doesn't incur. I'll probably stick with my current method for the moment.

Thread #189656. Printed from Allegro.cc