Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
93
67-04.md
Normal file
93
67-04.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](67-03.html) [Table of Contents](index.html) [Next](67-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
By the same token, Listing 67.1 is quite a bit more complicated than the
|
||||
earlier code. The earlier code’s HSR consisted of a z-sort of objects,
|
||||
followed by the drawing of the objects in back-to-front order, one
|
||||
polygon at a time. Apart from the simple object sorter, all that was
|
||||
needed was backface culling and a polygon rasterizer.
|
||||
|
||||
Listing 67.1 replaces this simple pipeline with a three-stage HSR
|
||||
process. After backface culling, the edges of each of the polygons in
|
||||
the scene are added to the global edge list, by way of
|
||||
**AddPolygonEdges()**. After all edges have been added, the edges are
|
||||
turned into spans by **ScanEdges()**, with each pixel on the screen
|
||||
being covered by one and only one span (that is, there’s no overdraw).
|
||||
Once all the spans have been generated, they’re drawn by
|
||||
**DrawSpans()**, and rasterization is complete.
|
||||
|
||||
There’s nothing tricky about **AddPolygonEdges()**, and **DrawSpans()**,
|
||||
as implemented in Listing 67.1, is very straightforward as well. In an
|
||||
implementation that supported texture mapping, however, all the spans
|
||||
wouldn’t be put on one global span list and drawn at once, as is done in
|
||||
Listing 67.1, because that would result in drawing spans from all the
|
||||
surfaces in no particular order. (A surface is a drawing object that’s
|
||||
originally described by a polygon, but in **ScanEdges()** there is no
|
||||
polygon in the classic sense of a set of vertices bounding an area, but
|
||||
rather just a set of edges and a surface that describes how to draw the
|
||||
spans outlined by those edges.) That would mean constantly skipping from
|
||||
one texture to another, which in turn would hurt processor cache
|
||||
coherency a great deal, and would also incur considerable overhead in
|
||||
setting up gradient and perspective calculations each time a surface was
|
||||
drawn. In Quake, we have a linked list of spans hanging off each
|
||||
surface, and draw all the spans for one surface before moving on to the
|
||||
next surface.
|
||||
|
||||
The core of Listing 67.1, and the most complex aspect of 1/z-sorted
|
||||
spans, is **ScanEdges()**, where the global edge list is converted into
|
||||
a set of spans describing the nearest surface at each pixel. This
|
||||
process is actually pretty simple, though, if you think of it as
|
||||
follows:
|
||||
|
||||
For each scan line, there is a set of active edges, which are those
|
||||
edges that intersect the scan line. A good part of **ScanEdges()** is
|
||||
dedicated to adding any edges that first appear on the current scan line
|
||||
(scan lines are processed from the top scan line on the screen to the
|
||||
bottom), removing edges that reach their bottom on the current scan
|
||||
line, and x-sorting the active edges so that the active edges for the
|
||||
next scan can be processed from left to right. All this is per-scan-line
|
||||
maintenance, and is basically just linked list insertion, deletion, and
|
||||
sorting.
|
||||
|
||||
The heart of the action is the loop in **ScanEdges()** that processes
|
||||
the edges on the current scan line from left to right, generating spans
|
||||
as needed. The best way to think of this loop is as a surface event
|
||||
processor, where each edge is an event with an associated surface. Each
|
||||
leading edge is an event marking the start of its surface on that scan
|
||||
line; if the surface is nearer than the current nearest surface, then a
|
||||
span ends for the nearest surface, and a span starts for the new
|
||||
surface. Each trailing edge is an event marking the end of its surface;
|
||||
if its surface is currently nearest, then a span ends for that surface,
|
||||
and a span starts for the next-nearest surface (the surface with the
|
||||
next-largest 1/z at the coordinate where the edge intersects the scan
|
||||
line). One handy aspect of this event-oriented processing is that
|
||||
leading and trailing edges do not need to be explicitly paired, because
|
||||
they are implicitly paired by pointing to the same surface. This saves
|
||||
the memory and time that would otherwise be needed to track edge pairs.
|
||||
|
||||
One more element is required in order for **ScanEdges()** to work
|
||||
efficiently. Each time a leading or trailing edge occurs, it must be
|
||||
determined whether its surface is nearest (at a larger 1/z value than
|
||||
any currently active surface). In addition, for leading edges, the
|
||||
currently topmost surface must be known, and for trailing edges, it may
|
||||
be necessary to know the currently next-to-topmost surface. The easiest
|
||||
way to accomplish this is with a *surface stack*; that is, a linked list
|
||||
of all currently active surfaces, starting with the nearest surface and
|
||||
progressing toward the farthest surface, which, as described below, is
|
||||
always the background surface. (The operation of this sort of edge
|
||||
event-based stack was described and illustrated in Chapter 66.) Each
|
||||
leading edge causes its surface to be 1/z-sorted into the surface stack,
|
||||
with a span emitted if necessary. Each trailing edge causes its surface
|
||||
to be removed from the surface stack, again with a span emitted if
|
||||
necessary. As you can see from Listing 67.1, it takes a fair bit of code
|
||||
to implement this, but all that’s really going on is a surface stack
|
||||
driven by edge events.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](67-03.html) [Table of Contents](index.html) [Next](67-05.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue