123 lines
7 KiB
Markdown
123 lines
7 KiB
Markdown
Chapter 68\
|
|
Quake's Lighting Model {#Heading1}
|
|
-----------------------
|
|
|
|
### A Radically Different Approach to Lighting Polygons {#Heading2}
|
|
|
|
It was during my senior year in college that I discovered computer
|
|
games. Not Wizardry, or Choplifter, or Ultima, because none of those
|
|
existed yet—the game that hooked me was the original Star Trek game, in
|
|
which you navigated from one 8x8 quadrant to another in search of
|
|
starbases, occasionally firing phasers or photon torpedoes. This was
|
|
less exciting than it sounds; after each move, the current quadrant had
|
|
to be reprinted from scratch, along with the current stats—and the
|
|
output device was a 10 cps printball console. A typical game took over
|
|
an hour, during which nothing particularly stimulating ever happened
|
|
(Klingons appeared periodically, but they politely waited for your next
|
|
move before attacking, and your photon torpedoes never missed, so the
|
|
outcome was never in doubt), but none of that mattered; nothing could
|
|
detract from the sheer thrill of being in a computer-simulated universe.
|
|
|
|
Then the college got a PDP-11 with four CRT terminals, and suddenly Star
|
|
Trek could redraw in a second instead of a minute. Better yet, I found
|
|
the source code for the Star Trek program in the recesses of the new
|
|
system, the first time I'd ever seen any real-world code other than my
|
|
own, and excitedly dove into it. One evening, as I was looking through
|
|
the code, a really cute girl at the next terminal asked me for help
|
|
getting a program to run. After I had helped her, eager to get to know
|
|
her better, I said, "Want to see something? This is the actual source
|
|
for the Star Trek game!" and proceeded to page through the code,
|
|
describing each subroutine. We got to talking, and eventually I worked
|
|
up the nerve to ask her out. She said sure, and we ended up having a
|
|
good time, although things soon fell apart because of her two or three
|
|
other boyfriends (I never did get an exact count). The interesting
|
|
thing, though, was her response when I finally got around to asking her
|
|
out. She said, "It's about time!" When I asked what she meant, she said,
|
|
"I've been trying to get you to ask me out all evening—but it took you
|
|
forever! You didn't actually think I was interested in that Star Trek
|
|
program, did you?"
|
|
|
|
Actually, yes, I had thought that, because *I* was interested in it. One
|
|
thing I learned from that experience, and have had reinforced countless
|
|
times since, is that we—you, me, anyone who programs because they love
|
|
it, who would do it for free if necessary—are a breed apart. We're
|
|
different, and luckily so; while everyone else is worrying about
|
|
downsizing, we're in one of the hottest industries in the world. And, so
|
|
far as I can see, the biggest reason we're in such a good situation
|
|
isn't intelligence, or hard work, or education, although those help;
|
|
it's that we actually *like* this stuff.
|
|
|
|
It's important to keep it that way. I've seen far too many people start
|
|
to treat programming like a job, forgetting the joy of doing it, and
|
|
burn out. So keep an eye on how you feel about the programming you're
|
|
doing, and if it's getting stale, it's time to learn something new;
|
|
there's plenty of interesting programming of all sorts to be done.
|
|
Follow your interests—and don't forget to have fun!
|
|
|
|
### The Lighting Conundrum {#Heading3}
|
|
|
|
I spent about two years working with John Carmack on Quake's 3-D
|
|
graphics engine. John faced several fundamental design issues while
|
|
architecting Quake. I've written in earlier chapters about some of those
|
|
issues, including eliminating non-visible polygons quickly via a
|
|
precalculated potentially visible set (PVS), and improving performance
|
|
by inserting potentially visible polygons into a global edge list and
|
|
scanning out only the nearest polygon at each pixel.
|
|
|
|
In this chapter, I'm going to talk about another, equally crucial design
|
|
issue: how we developed our lighting approach for the part of the Quake
|
|
engine that draws the world itself, the static walls and floors and
|
|
ceilings. Monsters and players are drawn using completely different
|
|
rendering code, with speed the overriding factor. A primary goal for the
|
|
world, on the other hand, was to be as precise as possible, getting
|
|
everything right so that polygons, textures, and sophisticated lighting
|
|
would be pegged in place, with no visible shifting or distortion under
|
|
all viewing conditions, for maximum player immersion—all with good
|
|
performance, of course. As I'll discuss, the twin goals of performance
|
|
and rock-solid, complex lighting proved to be difficult to achieve with
|
|
traditional lighting approaches; ultimately, a dramatically different
|
|
approach was required.
|
|
|
|
### Gouraud Shading {#Heading4}
|
|
|
|
The traditional way to do realistic lighting in polygon pipelines is
|
|
Gouraud shading (also known as *smooth shading*). Gouraud shading
|
|
involves generating a lighting value at each polygon vertex by applying
|
|
all relevant world lighting, linearly interpolating between lighting
|
|
values down the edges of the polygon, and then linearly interpolating
|
|
between the edges of the polygon across each span. If texture mapping is
|
|
desired (and all polygons are texture mapped in Quake), then at each
|
|
pixel in each span, the pixel's corresponding texture map location
|
|
(texel) is determined, and the interpolated lighting is applied to the
|
|
texel to generate a final, lit pixel. Texels are generally taken from a
|
|
32x32 or 64x64 texture that's tiled repeatedly across the polygon, for
|
|
several reasons: performance (a 64x64 texture sits nicely in the 486 or
|
|
Pentium cache), database size, and less artwork.
|
|
|
|
The interpolated lighting can consist of either a color intensity value
|
|
or three separate red, green, and blue values. RGB lighting produces
|
|
more sophisticated results, such as colored lights, but is slower and
|
|
best suited to RGB modes. Games like Quake that are targeted at
|
|
palettized 256-color modes generally use intensity lighting; each pixel
|
|
is lit by looking up the pixel color in a table, using the texel color
|
|
and the lighting intensity as the look-up indices.
|
|
|
|
Gouraud shading allows for decent lighting effects with a relatively
|
|
small amount of calculation and a compact data set that's a simple
|
|
extension of the basic polygon model. However, there are several
|
|
important drawbacks to Gouraud shading, as well.
|
|
|
|
#### Problems with Gouraud Shading {#Heading5}
|
|
|
|
The quality of Gouraud shading depends heavily on the average size of
|
|
the polygons being drawn. Linear interpolation is used, so highlights
|
|
can only occur at vertices, and color gradients are monotonic across the
|
|
face of each polygon. This can make for bland lighting effects if
|
|
polygons are large, and makes it difficult to do spotlights and other
|
|
detailed or dramatic lighting effects. After John brought the initial,
|
|
primitive Quake engine up using Gouraud shading for lighting, the first
|
|
thing he tried to improve lighting quality was adding a single vertex
|
|
and creating new polygons wherever a spotlight was directly overhead a
|
|
polygon, with the new vertex added directly underneath the light, as
|
|
shown in Figure 68.1. This produced fairly attractive highlights, but
|
|
simultaneously made evident several problems.
|