Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
104
66-04.md
Normal file
104
66-04.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](66-03.html) [Table of Contents](index.html) [Next](67-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
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.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](66-03.html) [Table of Contents](index.html) [Next](67-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue