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

126 lines
7.3 KiB
Markdown

#### The Subdivision Rasterizer {#Heading12}
This rasterizer, which we call the *subdivision rasterizer*, first draws
all the vertices in the model. Then it takes each front-facing triangle,
and determines if it has a side that's at least two pixels long. If it
does, we split that side into two pieces at the pixel nearest to the
middle (using adds and shifts to average the endpoints of that side),
draw the vertex at the split point, and process each of the two split
triangles recursively, until we get down to triangles that have only
one-pixel sides and hence have nothing left to draw. This approach is
hideously slow and quite ugly (due to inaccuracies from integer
quantization) for 100-pixel triangles—but it's very fast for, say,
five-pixel triangles, and is indistinguishable from more accurate
rasterization when a model is 25 or 50 feet away. Better yet, the
subdivider is ridiculously simple—a few dozen lines of code, far simpler
than the affine rasterizer—and was implemented in an evening,
immediately making the drawing of distant models about three times as
fast, a very good return for a bit of conceptual work. The affine
rasterizer got fairly close to the same performance with further
optimization—in the range of 10% to 50% slower—but that took weeks of
difficult programming.
We switch between the two rasterizers based on the model's distance and
average triangle size, and in almost any scene, most models are far
enough away so subdivision rasterization is used. There are undoubtedly
faster ways yet to rasterize distant models adequately well, but the
subdivider was clearly a win, and is a good example of how thinking in a
radically different direction can pay off handsomely.
#### Sprites {#Heading13}
We had hoped to be able to eliminate sprites completely, making Quake
100% 3-D, but sprites—although sometimes very visibly 2-D—were used for
a few purposes, most noticeably the cores of explosions. As of CGDC last
year, explosions consisted of an exploding spray of particles (discussed
below), but there just wasn't enough visual punch with that
representation; adding a series of sprites animating an explosion did
the trick. (In hindsight, we probably should have made the explosions
polygon models rather than sprites; it would have looked about as good,
and the few sprites we used didn't justify the considerable amount of
code and programming time required to support them.) Drawing a sprite is
similar to drawing a normal polygon, complete with perspective
correction, although of course the inner loop must detect and skip over
transparent pixels, and must also perform z-buffering.
#### Particles {#Heading14}
The last drawing entity type is particles. Each particle is a
solid-colored rectangle, scaled by distance from the viewer and drawn
with z-buffering. There can be up to 2,000 particles in a scene, and
they are used for rocket trails, explosions, and the like. In one sense,
particles are very primitive technology, but they allow effects that
would be extremely difficult to do well with the other types of
entities, and they work well in tandem with other entities, as, for
example, providing a trail of fire behind a polygon-model lava ball that
flies into the air, or generating an expanding cloud around a sprite
explosion core.
### How We Spent Our Summer Vacation: After Shipping Quake {#Heading15}
Since shipping Quake in the summer of 1996, we've extended it in several
ways: We've worked with Rendition to port it to the Verite accelerator
chip, we've ported it to OpenGL, we've ported it to Win32, we've done
QuakeWorld, and we've added features for Quake 2. I'll discuss each of
these briefly.
#### Verite Quake {#Heading16}
Verite Quake (VQuake) was the first hardware-accelerated version of
Quake. It looks extremely good, due to bilinear texture filtering, which
eliminates most pixel aliasing, and because it provides good performance
at higher resolutions such as 512x384 and 640x480. Implementing VQuake
proved to be an interesting task, for two reasons: The Verite chip's
fill rate was marginal for Quake's needs, and Verite contains a
programmable RISC chip, enabling more sophisticated processing than most
3-D accelerators. The need to squeeze as much performance as possible
out of Verite ruled out the use of a standard API such as Direct 3D or
OpenGL; instead, VQuake uses Rendition's proprietary API, Speedy3D, with
the addition of some special calls and custom Verite code.
Interestingly, VQuake is very similar to software Quake; in order to
allow Verite to handle the high pixel processing loads of high-res,
VQuake uses an edge list and builds span lists on the CPU, just as in
software Quake, then Verite DMAs the span descriptors to onboard memory
and draws them. (This was only possible because Verite is fully
programmable; most accelerators wouldn't be able to support this
architecture.) Similarly, the CPU builds lit, tiled surfaces in system
RAM, then Verite DMAs them to an onboard surface cache, from which they
are texture-mapped. In short, VQuake is very much like normal Quake,
except that the drawing of the spans is done by a specialized processor.
This approach works well, but some of the drawbacks of a surface cache
become more noticeable when hardware is involved. First, the DMAing is
an extra step that's not necessary in software, slowing things down.
Second, onboard memory is a relatively limited resource (4 MB total),
and textures must be 16-bpp (because hardware can only do filtering in
RGB modes), thus eating up twice as much memory as the software
version's 8-bpp textures—and memory becomes progressively scarcer at
higher resolutions, especially given the need for a z-buffer and two
16-bpp pages. (Note that using the edge list helps here, because it
filters out spans from polygons that are in the PVS but fully occluded,
reducing the number of surfaces that have to be downloaded.) Surface
caching in VQuake usually works just fine, but response when coming
around corners into complex scenes or when spinning can be more sluggish
than in software Quake.
An alternative to surface caching would have been to do two passes
across each span, one tiling the texture, and the other doing an alpha
blend using the light map as a texture, to light the texture (two-pass
alpha lighting). This approach produces exactly the same results as the
surface cache, without requiring downloading and caching of large
surfaces, and has the advantage of very level performance. However, this
approach requires at least twice the fill rate of the surface cache
approach, and Verite didn't have enough fill rate for that at higher
resolutions. It's also worth noting that two-pass alpha lighting doesn't
have the same potential for procedural texturing that surface caching
does. In fact, given MMX and ever-faster CPUs, and the ability of the
CPU and the accelerator to process in parallel, it will become
increasingly tempting to use the CPU to build surfaces with procedural
texturing such as bump mapping, shimmers, and warps; this sort of
procedural texturing has the potential to give accelerated games highly
distinctive visuals. So the choice between surface caching and two-pass
alpha lighting for hardware accelerators depends on a game's needs, and
it seems most likely that the two approaches will be mixed together,
with surface caching used for special surfaces, and two-pass alpha
lighting used for most drawing.