Precision in the z-buffer distance values is not spread evenly
over distance.
Nearer values are much more precise (and hence can display
closer objects more properly) than values which are farther away.
The range of depth values in camera space (see 3D projection) to be rendered is
often defined between a near and far value of z. After a perspective
transformation, the new value of z, or z', is defined by:
Where z is the old value of z in camera space.
The resulting values of z' are normalized between the values of -1 and 1, where
the near plane is at -1 and the far plane is at 1. Values outside of this range
correspond to points which are not in the viewing frustum, and shoudn't be
rendered.
The values of z' are grouped much more densely near the near plane, and much more sparsely farther away, resulting in better precision closer to the camera. The closer the near plane is set to the camera, the less precision there is far away -- having the near plane set too closely is a common cause of undesirable rendering artifacts in more distant objects.
Therefore, perspective division affects the accuracy of operations which rely
upon the transformed depth coordinate, especially depth-buffering, which is
used for hidden surface removal.
The depth (z) coordinate is encoded during the viewport transformation (and later stored in the depth buffer). You can scale z values to lie within a desired range with the glDepthRange() command.
Unlike x and y window coordinates, z window coordinates are treated by OpenGL as though they always range from 0.0 to 1.0.
void glDepthRange(GLclampd near, GLclampd far);Defines an encoding for z coordinates that is performed during the viewport transformation. The near and far values represent adjustments to the minimum and maximum values that can be stored in the depth buffer. By default, they're 0.0 and 1.0, respectively, which work for most applications. These parameters are clamped to lie within [0,1].
A variation on z-buffering which results in more evenly distributed precision is called w-buffering.
To implement a w-buffer, the old values of z in camera space, or w, are stored in the buffer, generally in floating point format. These values of w, as opposed to z', are spaced evenly between near and far.
Whether a z-buffer or w-buffer results in a better image depends on the application.