117 lines
6.9 KiB
Markdown
117 lines
6.9 KiB
Markdown
Chapter 70\
|
|
Quake: A Post-Mortem and a Glimpse into the Future {#Heading1}
|
|
---------------------------------------------------
|
|
|
|
*Why did not any of the children in the first group think of this faster
|
|
method of going across the room? It is simple. They looked at what they
|
|
were given to use for materials and, they are like all of us, they
|
|
wanted to use everything. But they did not need everything. They could
|
|
do better with less, in a different way.*
|
|
|
|
—*Frederik Pohl*, The Gold at the Starbow's End
|
|
|
|
Eleven years ago, I started the first serious graphics article I ever
|
|
wrote with the above quote. The point I was making at the time was that
|
|
programming assumptions based on high-level languages or other
|
|
processors had to be discarded in the quest for maximum x86 performance.
|
|
While that's certainly still true, time and the microcomputer world have
|
|
moved on, and today there's a more important lesson 3-D game programmers
|
|
can draw from Frederik Pohl's words. Nowadays, CPUs, 3-D hardware, 3-D
|
|
algorithms, and 3-D data structures are evolving so rapidly that the
|
|
enemy is now often the assumptions and techniques from the last
|
|
product—and sometimes the assumptions and techniques in the *current*
|
|
product. We all feel most comfortable with techniques we've already
|
|
mastered, but leading-edge 3-D game technology is such a delicate
|
|
balancing act between performance, features (particularly with game
|
|
designers always wanting to add more), and workflow (as we'll see,
|
|
preprocessing that improves performance often hurts designer
|
|
productivity) that it's never safe to stop looking for a better approach
|
|
until the game has actually shipped. Change is the rule, and we must
|
|
always be looking to "do better with less, in a different way."
|
|
|
|
I've talked about Quake's technology elsewhere in this book, However,
|
|
those chapters focused on specific areas, not overall structure.
|
|
Moreover, Quake changed in significant ways between the writing of those
|
|
chapters and the final shipping. Then, after shipping, Quake was ported
|
|
to 3-D hardware. And the post-Quake engine, code-named Trinity, is
|
|
already in development at this writing (Spring 1997), with some
|
|
promising results. So in wrapping up this book, I'll recap Quake's
|
|
overall structure relatively quickly, then bring you up to date on the
|
|
latest developments. And in the spirit of Frederik Pohl's quote, I'll
|
|
point out that we implemented and discarded at least half a dozen 3-D
|
|
engines in the course of developing Quake (and all of Quake's code was
|
|
written from scratch, rather than using Doom code), and almost switched
|
|
to another one in the final month, as I'll describe later. And even at
|
|
this early stage, Trinity uses almost no Quake technology.
|
|
|
|
In fact, I'll take this opportunity to coin Carmack's Law, as follows:
|
|
*Fight code entropy*. If you have a new fundamental assumption, throw
|
|
away your old code and rewrite it from scratch. Incremental patching and
|
|
modifying seems easier at first, and is the normal course of things in
|
|
software development, but ends up being much harder and producing
|
|
bulkier, markedly inferior code in the long run, as we'll see when we
|
|
discuss the net code for QuakeWorld. It may seem safer to modify working
|
|
code, but the nastiest bugs arise from unexpected side effects and
|
|
incorrect assumptions, which almost always arise in patched-over code,
|
|
not in code designed from the ground up. Do the hard work up front to
|
|
make your code simple, elegant, great—and just plain *right*—and it'll
|
|
pay off many times over in the long run.
|
|
|
|
Before I begin, I'd like to remind you that all of the Doom and Quake
|
|
material I'm presenting in this book is presented in the spirit of
|
|
sharing information to make our corner of the world a better place for
|
|
everyone. I'd like to thank John Carmack, Quake's architect and lead
|
|
programmer, and id Software for allowing me to share this technology
|
|
with you, and I encourage you to share your own insights by posting on
|
|
the Internet and writing books and articles whenever you have the
|
|
opportunity and the right to do so. (Of course, check with your employer
|
|
first!) We've all benefited greatly from the shared wisdom of people
|
|
like Knuth, Foley and van Dam, Jim Blinn, Jim Kajiya, and hundreds of
|
|
others—are you ready to take a shot at making your own contribution to
|
|
the future?
|
|
|
|
### Preprocessing the World {#Heading2}
|
|
|
|
For the most part, I'll discuss Quake's 3-D engine in this chapter,
|
|
although I'll touch on other areas of interest. For 3-D rendering
|
|
purposes, Quake consists of two basic sorts of objects: the world, which
|
|
is stored as a single BSP model and never changes shape or position; and
|
|
potentially moving objects, called *entities*, which are drawn in
|
|
several different ways. I'll discuss each separately.
|
|
|
|
The world is constructed from a set of brushes, which are n-sided convex
|
|
polyhedra placed in a level by a designer using a map editor, with a
|
|
selectable texture on each face. When a level is completed, a
|
|
preprocessing program combines all brushes to form a skin around the
|
|
solid areas of the world, so there is no interpenetration of polygons,
|
|
just a continuous mesh delineating solid and empty areas. Once this is
|
|
done, the next step is generating a BSP tree for the level.
|
|
|
|
The BSP consists of splitting planes aligned with polygons, called
|
|
nodes, and of leaves, which are the convex subspaces into which all the
|
|
nodes carve space. The top node carves the world into two subspaces, and
|
|
divides the remaining polygons into two sets, splitting any polygon that
|
|
spans the node into two pieces. Each subspace is then similarly split by
|
|
one node each, and so on until all polygons have been used to create
|
|
nodes. A node's subspace is the total space occupied by all its
|
|
children: the subspace that the node splits into two parts, and that its
|
|
children continue to subdivide. When the only polygon in a node's
|
|
subspace is the polygon that splits the subspace—the polygon whose plane
|
|
defines the node—then the two child subspaces are called leaves, and are
|
|
not divided any further.
|
|
|
|
The BSP tree is built using the polygon that splits the fewest of the
|
|
polygons in the current node's subspace as the heuristic for choosing
|
|
splitters, which is not an optimal solution—but an optimal solution is
|
|
NP-complete, and our heuristic adds only 10% to 15% more polygons to the
|
|
level as a result of BSP splits. Polygons are not split all the way into
|
|
leaves; rather, they are placed on the nodes with which they are
|
|
coplanar (one set on the front and one on the back, which has the
|
|
advantage of letting us reuse the BSP-walking dot product for backface
|
|
culling as well), thereby reducing splitting considerably, because
|
|
polygons are split only by parent nodes, not by child nodes (as would be
|
|
necessary if polygons were split into leaves). Eliminating polygon
|
|
splits, thus reducing the total number of polygons per level, not only
|
|
shrinks Quake's memory footprint, but also reduces the number of
|
|
polygons that need to be processed by the 3-D pipeline, producing a
|
|
speedup of about 10% in Quake's overall performance.
|