Z buffering

1What is a Z-Buffer?

In computer graphics, z-buffering, also known as depth buffering, is the management of image depth coordinates in 3D graphics, usually done in hardware, sometimes in software. It is one solution to the visibility problem, which is the problem of deciding which elements of a rendered scene are visible, and which are hidden.

When an object is rendered, the depth of a generated pixel (z coordinate) is stored in a buffer (the z-buffer or depth buffer). This buffer is usually arranged as a two-dimensional array (x-y) with one element for each screen pixel. If another object of the scene must be rendered with pixels at same coordinates, the method compares the two depths and overrides the current pixel if the object is closer to the observer. The new depth is then saved to the z-buffer, replacing the old one. In the end, the z-buffer will allow the method to correctly reproduce the usual depth perception: a close object hides a farther one. This is called z-culling.

The granularity of a z-buffer has a great influence on the scene quality: a 16-bit z-buffer can result in artifacts (called "z-fighting") when two objects are very close to each other. A 24-bit or 32-bit z-buffer behaves much better, although the problem cannot be entirely eliminated without additional algorithms. An 8-bit z-buffer is almost never used since it has too little precision.

The image below illustrates how a z-buffer works, this not the way it is really implemented (hardware or software). The camera has its Z axis oriented from the nearest visible point to the farthest visible point. So Z coordinates go from low values to high values when objects are far.

 

2Constraints on Palm OS devices

Devices running under Palm OS haven't got a lot of heap memory. This is a critical point that may you think about designing your application if you intend to use 3D rendering engine.

As Palm OS does not allow to natively allocate (easily) memory chunks larger than 64kb, I have decided to use an offscreen bitmap as Z buffer.

This offscreen bitmap is not used as a bitmap but as a large memory chunk. Images are well managed, using HB++, and destroyed when not used by the garbage collector.

 

3What about this choice?

Using a 32-bit Z-buffer would be great, allowing very good accuracy of computations and thus avoiding some graphics problems encountered sometimes . But due to a lack of memory on such devices I have decided to implement 16-bit Z-buffer.

So, I create and use a bitmap that I map to an HB++ Stream Memory object that allows getting a pointer to the reserved memory chunk.

Anyway, remember that 3D rendering engines use an offscreen bitmap for double buffering and an offscreen bitmap for z buffering... so a lot of memory.

As example, let's compute what would be the memory consumption for a 160x160 rendering window in double resolution and 16 bit colors:

  • Double buffer size = 4*160*160*2 = 204.8 kb
  • Z buffer size = 4*160*160*2 = 204.8 kb

So, about 409kb of memory.