Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
134
70-05.md
Normal file
134
70-05.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](70-04.html) [Table of Contents](index.html) [Next](70-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
### Entities {#Heading9}
|
||||
|
||||
So far, all we’ve drawn is the static, unchanging (apart from dynamic
|
||||
lighting) world. That’s an important foundation, but it’s certainly not
|
||||
a game; now we need to add moving objects. These objects fall into four
|
||||
very different categories: BSP models, polygon models, sprites, and
|
||||
particles.
|
||||
|
||||
#### BSP Models {#Heading10}
|
||||
|
||||
BSP models are just like the world, except that they can move. Examples
|
||||
include doors, moving bridges, and health and ammo boxes. The way these
|
||||
are rendered is by clipping their polygons into the world BSP tree, so
|
||||
each polygon fragment is in only one leaf. Then these fragments are
|
||||
added to the edge list, just like world polygons, and scanned out, along
|
||||
with the rest of the world, when the edge list is processed. The only
|
||||
trick here is front-to-back ordering. Each BSP model polygon fragment is
|
||||
given the BSP sorting order of the leaf in which it resides, allowing it
|
||||
to sort properly versus the world polygons. If two or more polygons from
|
||||
different BSP models are in the same leaf, however, BSP ordering is no
|
||||
longer useful, so we then sort those polygons by 1/z, calculated from
|
||||
the polygons’ plane equations.
|
||||
|
||||
Interesting note: We originally tried to sort all world polygons on 1/z
|
||||
as well, the reason being that we could then avoid splitting polygons
|
||||
except when they actually intersected, rather than having to split them
|
||||
along the lines of parent nodes. This would result in fewer edges, and
|
||||
faster edge list processing and rasterization. Unfortunately, we found
|
||||
that precision errors and special cases such as seamlessly abutting
|
||||
objects made it difficult to get global 1/z sorting to work completely
|
||||
reliably, and the code that we had to add to work around these problems
|
||||
slowed things up to the point where we were getting no extra performance
|
||||
for all the extra code complexity. This is not to say that 1/z sorting
|
||||
can’t work (especially in something like a flight sim, where objects
|
||||
never abut), but BSP sorting order can be a wonderful thing, partly
|
||||
because it always works perfectly, and partly because it’s simpler and
|
||||
faster to sort on integer node and leaf orders than on floating-point
|
||||
1/z values.
|
||||
|
||||
BSP models take some extra time because of the cost of clipping them
|
||||
into the world BSP tree, but render just as fast as the rest of the
|
||||
world, again with no overdraw, so closed doors, for example, block
|
||||
drawing of whatever’s on the other side (although it’s still necessary
|
||||
to transform, project, and add to the edge list the polygons the door
|
||||
occludes, because they’re still in the PVS—they’re potentially visible
|
||||
if the door opens). This makes BSP models most suitable for fairly
|
||||
simple structures, such as boxes, which have relatively few polygons to
|
||||
clip, and cause relatively few edges to be added to the edge list.
|
||||
|
||||
#### Polygon Models and Z-Buffering {#Heading11}
|
||||
|
||||
Polygon models, such as monsters, weapons, and projectiles, consist of a
|
||||
triangle mesh with front and back skins stretched over the model. For
|
||||
speed, the triangles are drawn with affine texture mapping; the
|
||||
triangles are small enough, and the models are generally distant enough,
|
||||
that affine distortion isn’t visible. (However, it is visible on the
|
||||
player’s weapon; this caused a lot of extra work for the artists, and we
|
||||
will probably implement a perspective-correct polygon-model rasterizer
|
||||
in Quake 2 for this specific purpose.) The triangles are also Gouraud
|
||||
shaded; interestingly, the light vector used to shade the models is
|
||||
always from the same direction, and has no relation to any actual lights
|
||||
in the world (although it does vary in intensity, along with the model’s
|
||||
ambient lighting, to match the brightness of the spot the player is
|
||||
standing above in the world). Even this highly inaccurate lighting works
|
||||
well, though; the Gouraud shading makes models look much more
|
||||
three-dimensional, and varying the lighting in even so crude a way
|
||||
allows hiding in shadows and illumination by explosions and muzzle
|
||||
flashes.
|
||||
|
||||
One issue with polygon models was how to handle occlusion issues; that
|
||||
is, what parts of models were visible, and what surfaces they were in
|
||||
front of. We couldn’t add models to the edge list, because the hundreds
|
||||
of polygons per model would overwhelm the edge list. Our initial
|
||||
occlusion solution was to sort polygon-model polygons into the world
|
||||
BSP, drawing the portions in each leaf at the right points as we drew
|
||||
the world in BSP order. That worked reasonably well with respect to the
|
||||
world (not perfectly, though, because it would have been too expensive
|
||||
to clip all the polygon-model polygons into the world, so there was some
|
||||
occlusion error), but didn’t handle the case of sorting polygon models
|
||||
in the same leaf against each other, and also didn’t help the polygons
|
||||
in a given polygon model sort properly against each other.
|
||||
|
||||
The solution to this turned out to be z-buffering. After all the spans
|
||||
in the world are drawn, the z-buffer is filled in for those spans. This
|
||||
is a write-only operation, and involves no comparisons or overdraw
|
||||
(remember, the spans cover every pixel on the screen exactly once), so
|
||||
it’s not that expensive—the performance cost is about 10%. Then polygon
|
||||
models are drawn with z-buffering; this involves a z-compare at each
|
||||
polygon-model pixel, but no complicated clipping or sorting—and
|
||||
occlusion is exactly right in all respects. Polygon models tend to
|
||||
occupy a small portion of the screen, so the cost of z-buffering is not
|
||||
that high, anyway.
|
||||
|
||||
Opinions vary as to the desirability of z-buffers; some people who favor
|
||||
more analytical approaches to hidden surface removal claim that John has
|
||||
been seduced by the z-buffer. Maybe so, but there’s a lot there to be
|
||||
seduced by, and that will be all the more true as hardware rendering
|
||||
becomes the norm. The addition of particles—thousands of tiny colored
|
||||
rectangles—to Quake illustrated just how seductive the z-buffer can be;
|
||||
it would have been very difficult to get all those rectangles to draw
|
||||
properly using any other occlusion technique. Certainly z-buffering by
|
||||
itself can’t perform well enough to serve for all hidden surface
|
||||
removal; that’s why we have the PVS and the edge list (although for
|
||||
hardware rendering the PVS would suffice), but z-buffering pretty much
|
||||
means that if you can figure out how to draw an effect, you can readily
|
||||
insert it into the world with proper occlusion, and that’s a powerful
|
||||
capability indeed.
|
||||
|
||||
Supporting scenes with a dozen or more models of 300 to 500 polygons
|
||||
each was a major performance challenge in Quake, and the polygon-model
|
||||
drawing code was being optimized right up until the last week before it
|
||||
shipped. One help in allowing more models per scene was the PVS; we only
|
||||
drew those models that were in the PVS, meaning that levels could have a
|
||||
hundred or more models without requiring a lot of work to eliminate most
|
||||
of those that were occluded. (Note that this is not unique to the PVS;
|
||||
whatever high-level culling scheme we had ended up using for world
|
||||
polygons would have provided the same benefit for polygon models.) Also,
|
||||
model bounding boxes were used to trivially clip those that weren’t in
|
||||
the view pyramid, and to identify those that were unclipped, so they
|
||||
could be sent through a special fast path. The biggest breakthrough,
|
||||
though, was a very different sort of rasterizer that John came up with
|
||||
for relatively distant models.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](70-04.html) [Table of Contents](index.html) [Next](70-06.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue