OpenGL Depth Sorting Resolution

by James W. Walker

Depth sorting is the process by which OpenGL decides whether one triangle is in front of another. If the triangles are too close together, the process may fail. Whether depth sorting succeeds or fails depends on a number of variables: The distances of the triangles from the camera, the distances of the near and far clipping planes from the camera, and the size of the depth buffer. This article explores the relationship between these variables and depth sorting. See http://www.opengl.org/resources/faq/technical/depthbuffer.htm#dept0045 for a similar discussion.

Review of Coordinate Systems in OpenGL

The viewing transformation transforms object coordinates into eye coordinates, also known as view coordinates. The eye coordinate system has its origin at the camera location (the "eye"), x axis to the right, y axis up, and (to make the coordinate system right-handed) -z axis in the direction that the camera is looking.

The volume visible to a perspective camera is a frustum of a pyramid, bounded by 4 planes on the left, right, top, and bottom, and by the near and far clipping planes. The projection matrix maps this volume to a box in clip coordinates, also called frustum coordinates, in which x, y, and z each range from -w to w. Division of x, y, and z by w, called perspective division, brings us to normalized device coordinates, where x, y, and z range from -1 to 1.

The viewport transformation maps normalized device coordinates to window coordinates. In particular, the z coordinate maps into the range 0 to 1. These z values are then stored in the depth buffer for depth sorting. Notice that the range 0 to 1 means that the depth buffer does not need to store a sign bit or an exponent, unlike the usual case with floating-point numbers.

Window Depth as a Function of Eye Depth

The projection matrix defined by gluPerspective is:

 
f
aspect
0 0 0
0 f 0 0
0 0
zFar + zNear
zNear - zFar
2 zFar zNear
zNear - zFar
0 0 -1 0
 

Therefore a point with eye coordinates ( ·, ·, -d, 1 )T is transformed to the point in clip coordinates

( ·, ·,
- d (zFar + zNear) + 2 zFar zNear
zNear - zFar
, d )T.

The perspective division brings us to normalized device coordinates

( ·, ·,
zFar + zNear
zFar - zNear
-
2 zFar zNear
d (zFar - zNear)
, 1 )T.

When we transform normalized device coordinates to window coordinates, the depth coordinate is transformed by the linear function x → x/2 + 1/2, producing

( ·, ·,
zFar + zNear
2 (zFar - zNear)
-
zFar zNear
d (zFar - zNear)
+ 0.5, 1 )T.

Therefore, window depth as a function of eye depth is given by the formula

f( d ) =
zFar + zNear
2 (zFar - zNear)
-
zFar zNear
d (zFar - zNear)
+ 0.5 .

You can easily check that f( zNear ) = 0 and f( zFar ) = 1.

Estimating Depth Resolution

Consider two triangles at eye coordinate depths d1 and d2, differing by Δd. I want to estimate how large Δd can be in a situation where the two triangles cannot be reliably sorted by the depth buffer.

If the depth buffer is k bits deep, then the minimum significant difference in window depth is Δf = 2-k. To relate Δd to Δf, we can use the approximation for the derivative,

f'( d ) ≈
Δf
Δd

or

Δd ≈
Δf
f'( d )
.

The exact formula for the derivative is

f'( d ) =
zFar zNear
d2 (zFar - zNear)
,

hence we obtain

Δd ≈ 2-k
d2 (zFar - zNear)
zFar zNear
,

Clearly, the worst case is near the far plane, where this reduces to

Δd ≈ 2-k
zFar (zFar - zNear)
zNear
.

Typically, the ratio of zFar to zNear is large, so we do not lose much by using the cruder estimate

 
Δd ≈ 2-k
zFar2
zNear
.
(1)

Exact Calculation of Depth Resolution

We want to find the largest value of Δd such that

  f( d ) - f( d - Δd ) = Δf (2)

and such that d and d - Δd are restricted to the interval from zNear to zFar.

We can express the function as

f( x ) = a - b/x

where

b =
zFar zNear
zFar - zNear
.

Now let us solve equation (1) for Δd.

a - b/d - (a - 
b
d - Δd
) = Δf

Cancel the a.

b
d - Δd
 - 
b
d
 = Δf

Divide through by b.

1
d - Δd
 - 
1
d
 = 
Δf
b

Solve for d - Δd.

1
d - Δd
 = 
1
d
 + 
Δf
b
 = 
b + d Δf
b d

 

d - Δd = 
b d
b + d Δf

And finally we can obtain Δd.

Δd = d - 
b d
b + d Δf
 = 
d b + d2 Δf - b d
b + d Δf
 = 
d2 Δf
b + d Δf

If we write this as

Δd =  
d Δf
b/d + Δf

then it is clear that the numerator is an increasing function of d and the denominator is a decreasing function of d, so the maximum occurs at the right hand end of the interval, d = zFar. If we substitute in d = zFar, Δf = 2-k, and the defined value of b, we have:

Δd =  
zFar 2-k
zNear
zFar - zNear
 + 2-k

or equivalently

 
Δd =  
zFar (zFar - zNear) 2-k
zNear + (zFar - zNear) 2-k
 .
(3)

If we assume that the ratio zFar/zNear is much larger than 1 but much smaller than 2k, then we can see that the approximation (1) is a reasonable approximation to equation (3).

Copyright ©2006, James W. Walker