If you wish to compute the Z-buffer near & far planes automatically for a scene, you may run into a problem when your Z-buffer bounds are exact. Faces that lie exactly on the near or far clipping plane may be discarded either by comparison convention or by roundoff error.

This method widens the Z-volume such that only *epsilon* is lost off either end *in
perspective space*. Note that widening the bounds by just adding and subtracting a fixed epsilon
from the near and far planes directly will typically consume far too much Z resolution at your near
plane, and not enough at your far plane.

To illustrate this, the following table shows the values for a given min and max Z depth, and sets hither and yon with a fixed epsilon of 1/1000th the distance from near to far. Note that the Z-buffer values are for a 16-bit Z-buffer (0–65535), and that the computed Z values are in [0,-1]:

Min Depth | Max Depth | Computed Hither | Computed Yon | Zbuffer Min | Zbuffer Max |
---|---|---|---|---|---|

-1 | -2 | -0.999000000 | -2.001000000 | 130.8738 | 65502.3306 |

-1 | -10 | -0.991000000 | -10.00900000 | 654.6306 | 65528.5184 |

-1 | -100 | -0.901000000 | -100.0990000 | 6546.8942 | 65534.4107 |

-0.1 | -100 | -0.000100000 | -100.0999000 | 65469.5304 | 65534.9999 |

-0.1 | -1000 | +0.899900000 | -1000.999900 | overflow |
65535.0589 |

Note that the near plane continues to waste Z space until the point that it overflows the perspective depth calculation (since the fixed delta causes it to go positive for large enough depth). In addition, note that the far plane is not positioned far enough away in the last two cases.

In constrast, the following table illustrates the formulas to calculate *hither* and
*yon* such that the near and far planes are exactly 1.5 clicks (in Z-buffer coordinates) from
the near and far planes:

Min Depth | Max Depth | Computed Hither | Computed Yon | Zbuffer Min | Zbuffer Max |
---|---|---|---|---|---|

-1 | -2 | -0.999988555 | -2.000045780 | 1.5000 | 65533.5000 |

-1 | -10 | -0.999979400 | -10.00206049 | 1.5000 | 65533.5000 |

-1 | -100 | -0.999977340 | -100.2271215 | 1.5000 | 65533.5000 |

-0.1 | -100 | -0.099997713 | -102.3401813 | 1.5000 | 65533.5000 |

-0.1 | -1000 | -0.099997711 | -1296.803111 | 1.5000 | 65533.5000 |

Perfect! Each point at the min depth lies exactly 1.5 clicks in from the front, and each point at the max depth lies 1.5 clicks shy of the far plane. Here's how it's done:

With this method, define *epsilon* to be the number of clicks in Z-buffer coordinates that
you want to widen the Z space. In other words,

number of clicksepsilon= ---------------- (2^{bitdepth}) - 1

Given the *epsilon* computed above, *Z _{near}* (the nearest world-coordinate
point in

Z*_{near}Z* (2*_{far}epsilon- 1)hither= -------------------------------- [Eq 1a]epsilon* (Z+_{near}Z) -_{far}Z_{far}Z*_{near}Z* (2*_{far}epsilon- 1)yon= -------------------------------- [Eq 1b]epsilon* (Z+_{near}Z) -_{far}Z_{near}

These formulas work whether you're in right-handed coordinates or in left-handed coordinates. The derivation changes slightly, but the results are identical.

We seek *hither* & *yon* such that

Zdepth(a) = -epsilon Zdepth(b) = -1 + epsilon [Eq 2]

where *a* is the closest Z value and *b* is the furthest (we are
mapping *Z* to [0,-1]).

The perspective depth equation for this is

(Z - hither) * yon Zdepth(Z) = --------------------- [Eq 3] (yon - hither) * (-Z)

[Note that these are for Z mappings to [0,-1]. If you are mapping Z to the range [0,1] (usually
if you're using left-handed coordinates), then negate equations [Eq 2] and [Eq 3]. You'll note in
the following derivation that both forms yield identical solutions for *hither* and
*yon*.]

Now we seek the values for *hither* and *yon* such that we get the Z depths for
*a* and *b* as noted above in equation 1. For brevity, let *e = epsilon*, *h =
hither* and *y = yon*. First we find *hither*:

(a-h)y (b-h)y --------- = -e --------- = -1 + e (y-h)(-a) (y-h)(-b) ae y y b(1-e) --- = --- --- = ------ a-h y-h y-h b-h ae b(1-e) --- = ------ a-h b-h ae(b-h) = b(a-h)(1-e) aeb - aeh = ab(1-e) - bh(1-e) aeb - ab(1-e) = aeh - bh(1-e) ab(e - (1-e)) = h(ae - b(1-e)) ab(e - (1-e)) = h(e(a+b) - b) ab (2e-1) h = ----------- [Eq 1a] e(a+b) - b

Finding yon in a similar manner, we get the nearly identical equation 1b. Again, these formulas
for *hither* and *yon* can be used regardless of the handedness of the camera coordinate
system (right-handed or left-handed).

Steve Hollasch / 1996 December 18