abrash-black-book/66-04.md
2013-12-30 20:26:41 +11:00

92 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

The obvious way to get a 1/z value at any arbitrary point on a polygon
is to calculate 1/z at the vertices, interpolate it down both edges of
the polygon, and interpolate between the edges to get the value at the
point of interest. Unfortunately, that requires doing a lot of work
along each edge, and worse, requires division to calculate the 1/z step
per pixel across each span.
A better solution is to calculate 1/z directly from the plane equation
and the screen x and y of the pixel of interest. The equation is
1/z = (a/d)x' - (b/d)y' + c/d
where z is the viewspace z coordinate of the point on the plane that
projects to screen coordinate (x',y') (the origin for this calculation
is the center of projection, the point on the screen straight ahead of
the viewpoint), [a b c] is the plane normal in viewspace, and d is the
distance from the viewspace origin to the plane along the normal.
Division is done only once per plane, because a, b, c, and d are
per-plane constants.
The full 1/z calculation requires two multiplies and two adds, all of
which should be floating-point to avoid range errors. That much
floating-point math sounds expensive but really isn't, especially on a
Pentium, where a plane's 1/z value at any point can be calculated in as
little as six cycles in assembly language.
#### Where That 1/Z Equation Comes From {#Heading10}
For those who are interested, here's a quick derivation of the 1/z
equation. The plane equation for a plane is
ax + by + cz - d = 0
where x and y are viewspace coordinates, and a, b, c, d, and z are
defined above. If we substitute x=x'z and y=-y'z (from the definition of
the perspective projection, with y inverted because y increases upward
in viewspace but downward in screenspace), and do some rearrangement, we
get:
z = d / (ax' - by' + c)
Inverting and distributing yields:
= ax'/d - by'/d + c/d
We'll see 1/z sorting in action in Chapter 67.
#### Quake and Z-Sorting {#Heading11}
I mentioned earlier that Quake no longer uses BSP order as the sorting
key; in fact, it uses 1/z as the key now. Elegant as the gradients are,
calculating 1/z from them is clearly slower than just doing a compare on
a BSP-ordered key, so why have we switched Quake to 1/z?
The primary reason is to reduce the number of polygons. Drawing in BSP
order means following certain rules, including the rule that polygons
must be split if they cross BSP planes. This splitting increases the
numbers of polygons and edges considerably. By sorting on 1/z, we're
able to leave polygons unsplit but still get correct drawing order, so
we have far fewer edges to process and faster drawing overall, despite
the added cost of 1/z sorting.
Another advantage of 1/z sorting is that it solves the sorting issues I
mentioned at the start involving moving models that are themselves small
BSP trees. Sorting in world BSP order wouldn't work here, because these
models are separate BSPs, and there's no easy way to work them into the
world BSP's sequence order. We don't want to use z-buffering for these
models because they're often large objects such as doors, and we don't
want to lose the overdraw-reduction benefits that closed doors provide
when drawn through the edge list. With sorted spans, the edges of moving
BSP models are simply placed in the edge list (first clipping polygons
so they don't cross any solid world surfaces, to avoid complications
associated with interpenetration), along with all the world edges, and
1/z sorting takes care of the rest.
### Decisions Deferred {#Heading12}
There is, without a doubt, an awful lot of information in the preceding
pages, and it may not all connect together yet in your mind. The code
and accompanying explanation in the next chapter should help; if you
want to peek ahead, the code is available on the CD-ROM as DDJZSORT.ZIP
in the directory for Chapter 67. You may also want to take a look at
Foley and van Dam's *Computer Graphics* or Rogers' *Procedural Elements
for Computer Graphics*.
As I write this, it's unclear whether Quake will end up sorting edges by
BSP order or 1/z. Actually, there's no guarantee that sorted spans in
any form will be the final design. Sometimes it seems like we change
graphics engines as often as they play Elvis on the ‘50s oldies stations
(but, one would hope, with more aesthetically pleasing results!) and no
doubt we'll be considering the alternatives right up until the day we
ship.