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

121 lines
8 KiB
Markdown

When I came in on Monday, John had the look of a man who had broken
through to the other side—and also the look of a man who hadn't had much
sleep. He had worked all weekend on the direct-BSP approach, and had
gotten it working reasonably well, with insights into how to finish it
off. At 3:30 Monday morning, as he lay in bed, thinking about portals,
he thought of precalculating and storing in each leaf a list of all
leaves visible from that leaf, and then at runtime just drawing the
visible leaves back-to-front for whatever leaf the viewpoint happens to
be in, ignoring all other leaves entirely.
Size was a concern; initially, a raw, uncompressed potentially visible
set (PVS) was several megabytes in size. However, the PVS could be
stored as a bit vector, with 1 bit per leaf, a structure that shrunk a
great deal with simple zero-byte compression. Those steps, along with
changing the BSP heuristic to generate fewer leaves (choosing as the
next splitter the polygon that splits the fewest other polygons appears
to be the best heuristic) and sealing the outside of the levels so the
BSPer can remove the outside surfaces, which can never be seen,
eventually brought the PVS down to about 20 Kb for a good-size level.
In exchange for that 20 Kb, culling leaves outside the frustum is
speeded up (because only leaves in the PVS are considered), and culling
inside the frustum costs nothing more than a little overdraw (the PVS
for a leaf includes all leaves visible from anywhere in the leaf, so
some overdraw, typically on the order of 50 percent but ranging up to
150 percent, generally occurs). Better yet, precalculating the PVS
results in a leveling of performance; worst case is no longer much worse
than best case, because there's no longer extra VSD processing—just more
polygons and perhaps some extra overdraw—associated with complex scenes.
The first time John showed me his working prototype, I went to the most
complex scene I knew of, a place where the frame rate used to grind down
into the single digits, and spun around smoothly, with no perceptible
slowdown.
John says precalculating the PVS was a logical evolution of the
approaches he had been considering, that there was no moment when he
said "Eureka!" Nonetheless, it was clearly a breakthrough to a
brand-new, superior design, a design that, together with a
still-in-development sorted-edge rasterizer that completely eliminates
overdraw, comes remarkably close to meeting the "perfect-world"
specifications we laid out at the start.
### Simplify, and Keep on Trying New Things {#Heading16}
What does it all mean? Exactly what I said up front: Simplify, and keep
trying new things. The precalculated PVS is simpler than any of the
other schemes that had been considered (although precalculating the PVS
is an interesting task that I'll discuss another time). In fact, at
runtime the precalculated PVS is just a constrained version of the
painter's algorithm. Does that mean it's not particularly profound?
Not at all. All really great designs seem simple and even obvious—once
they've been designed. But the process of getting there requires
incredible persistence and a willingness to try lots of different ideas
until the right one falls into place, as happened here.
------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
![](images/i.jpg) *My friend Chris Hecker has a theory that all approaches work out to the same thing in the end, since they all reflect the same underlying state and functionality. In terms of underlying theory, I've found that to be true; whether you do perspective texture mapping with a divide or with incremental hyperbolic calculations, the numbers do exactly the same thing. When it comes to implementation, however, my experience is that simply time-shifting an approach, or matching hardware capabilities better, or caching can make an astonishing difference.*
------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
My friend Terje Mathisen likes to say that "almost all programming can
be viewed as an exercise in caching," and that's exactly what John did.
No matter how fast he made his VSD calculations, they could never be as
fast as precalculating and looking up the visibility, and his most
inspired move was to yank himself out of the "faster code" mindset and
realize that it was in fact possible to precalculate (in effect, cache)
and look up the PVS.
The hardest thing in the world is to step outside a familiar, pretty
good solution to a difficult problem and look for a different, better
solution. The best ways I know to do that are to keep trying new, wacky
things, and always, always, always try to simplify. One of John's goals
is to have fewer lines of code in each 3-D game than in the previous
game, on the assumption that as he learns more, he should be able to do
things better with less code.
So far, it seems to have worked out pretty well for him.
### Learn Now, Pay Forward {#Heading17}
There's one other thing I'd like to mention before I close this chapter.
Much of what I've learned, and a great deal of what I've written, has
been in the pages of *Dr. Dobb's Journal.* As far back as I can
remember, *DDJ* has epitomized the attitude that sharing programming
information is A Good Thing. I know a lot of programmers who were able
to leap ahead in their development because of Hendrix's Tiny C, or
Stevens' D-Flat, or simply by browsing through *DDJ*'s annual
collections. (Me, for one.) Understandably, most companies
understandably view sharing information in a very different way, as
potential profit lost—but that's what makes *DDJ* so valuable to the
programming community.
It is in that spirit that id Software is allowing me to describe in
these pages (which also appeared in one of the *DDJ* special issues) how
Quake works, even before Quake has shipped. That's also why id has
placed the full source code for Wolfenstein 3-D on
[ftp.idsoftware.com/idstuff/source](ftp://ftp.idsoftware.com/idstuff/source);
and although you can't just recompile the code and sell it, you can
learn how a full-blown, successful game works. Check wolfsrc.txt in the
above-mentioned directory for details on how the code may be used.
So remember, when it's legally possible, sharing information benefits us
all in the long run. You can pay forward the debt for the information
you gain here and elsewhere by sharing what you know whenever you can,
by writing an article or book or posting on the Net. None of us learns
in a vacuum; we all stand on the shoulders of giants such as Wirth and
Knuth and thousands of others. Lend your shoulders to building the
future!
### References {#Heading18}
Foley, James D., *et al.*, *Computer Graphics: Principles and Practice*,
Addison Wesley, 1990, ISBN 0-201-12110-7 (beams, BSP trees, VSD).
Teller, Seth, *Visibility Computations in Densely Occluded Polyhedral
Environments* (dissertation), available on
[http://theory.lcs.mit.edu/\~seth/](http://theory.lcs.mit.edu/~seth/)
along with several other papers relevant to visibility determination.
Teller, Seth, *Visibility Preprocessing for Interactive Walkthroughs*,
SIGGRAPH 91 proceedings, pp. 61-69.