Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
147
68-02.md
Normal file
147
68-02.md
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](68-01.html) [Table of Contents](index.html) [Next](68-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
A primary problem with Gouraud shading is that it requires the vertices
|
||||
used for world geometry to serve as lighting sample points as well, even
|
||||
though there isn’t necessarily a close relationship between lighting and
|
||||
geometry. This artificial coupling often forces the subdivision of a
|
||||
single polygon into several polygons purely for lighting reasons, as
|
||||
with the spotlights mentioned above; these extra polygons increase the
|
||||
world database size, and the extra transformations and projections that
|
||||
they induce can harm performance considerably.
|
||||
|
||||
Similar problems occur with overlapping lights, and with shadows, where
|
||||
additional polygons are required in order to approximate lighting detail
|
||||
well. In particular, good shadow edges need small polygons, because
|
||||
otherwise the gradient between light and dark gets spread across too
|
||||
wide an area. Worse still, the rate of lighting change across a shadow
|
||||
edge can vary considerably as a function of the geometry the edge
|
||||
crosses; wider polygons stretch and diffuse the transition between light
|
||||
and shadow. A related problem is that lighting discontinuities can be
|
||||
very visible at t-junctions (although ultimately we had to add edges to
|
||||
eliminate t-junctions anyway, because otherwise dropouts can occur along
|
||||
polygon edges). These problems can be eased by adding extra edges, but
|
||||
that increases the rasterization load.
|
||||
|
||||
\
|
||||
**Figure 68.1** *Adding an extra vertex directly beneath a light.*
|
||||
|
||||
#### Perspective Correctness {#Heading6}
|
||||
|
||||
Another problem is that Gouraud shading isn’t perspective-correct. With
|
||||
Gouraud shading, lighting varies linearly across the face of a polygon,
|
||||
in equal increments per pixel—but unless the polygon is parallel to the
|
||||
screen, the same sort of perspective correction is needed to step
|
||||
lighting across the polygon properly as is required for texture mapping.
|
||||
Lack of perspective correction is not as visibly wrong for lighting as
|
||||
it is for texture mapping, because smooth lighting gradients can
|
||||
tolerate considerably more warping than can the detailed bitmapped
|
||||
images used in texture mapping, but it nonetheless shows up in several
|
||||
ways.
|
||||
|
||||
First, the extent of the mismatch between Gouraud shading and
|
||||
perspective lighting varies with the angle and orientation of the
|
||||
polygon being lit. As a polygon turns to become more on-edge, for
|
||||
example, the lighting warps more and therefore shifts relative to the
|
||||
perspective-texture mapped texels it’s shading, an effect I’ll call
|
||||
*viewing variance*. Lighting can similarly shift as a result of
|
||||
clipping, for example if one or more polygon edges are completely
|
||||
clipped; I’ll refer to this as *clipping variance*.
|
||||
|
||||
These are fairly subtle effects; more pronounced is the *rotational
|
||||
variance* that occurs when Gouraud shading any polygon with more than
|
||||
three vertices. Consistent lighting for a polygon is fully defined by
|
||||
three lighting values; taking four or more vertices and interpolating
|
||||
between them, as Gouraud shading does, is basically a hack, and does not
|
||||
reflect any consistent underlying model. If you view a Gouraud-shaded
|
||||
quad head-on, then rotate it like a pinwheel, the lighting will shift as
|
||||
the quad turns, as shown in Figure 68.2. The extent of the lighting
|
||||
shift can be quite drastic, depending on how different the colors at the
|
||||
vertices are.
|
||||
|
||||
It was rotational variance that finally brought the lighting issue to a
|
||||
head for Quake. We’d look at the floors, which were Gouraud-shaded
|
||||
quads; then we’d pivot, and the lighting would shimmy and shift,
|
||||
especially where there were spotlights and shadows. Given the goal of
|
||||
rendering the world as accurately and convincingly as possible, this was
|
||||
unacceptable.
|
||||
|
||||
The obvious solution to rotational variance is to use only triangles,
|
||||
but that brings with it a new set of problems. It takes twice as many
|
||||
triangles as quads to describe the same scene, increasing the size of
|
||||
the world database and requiring extra rasterization, at a performance
|
||||
cost. Triangles still don’t provide perspective lighting; their lighting
|
||||
is rotationally invariant, but it’s still wrong—just wrong in a more
|
||||
consistant way. Gouraud-shaded triangles still result in odd lighting
|
||||
patterns, and require lots of triangles to support shadowing and other
|
||||
lighting detail. Finally, triangles don’t solve clipping or viewing
|
||||
variance.
|
||||
|
||||
\
|
||||
**Figure 68.2** *How Gouraud shading varies with polygon screen
|
||||
orientation.*
|
||||
|
||||
Yet another problem is that while it may work well to add extra geometry
|
||||
so that spotlights and shadows show up well, that’s feasible only for
|
||||
static lighting. Dynamic lighting—light cast by sources that move—has to
|
||||
work with whatever geometry the world has to offer, because its needs
|
||||
are constantly changing.
|
||||
|
||||
These issues led us to conclude that if we were going to use Gouraud
|
||||
shading, we would have to build Quake levels from many small triangles,
|
||||
with sufficiently finely detailed geometry so that complex lighting
|
||||
could be supported and the inaccuracies of Gouraud shading wouldn’t be
|
||||
too noticeable. Unfortunately, that line of thinking brought us back to
|
||||
the problem of a much larger world database and a much heavier
|
||||
rasterization load (all the worse because Gouraud shading requires an
|
||||
additional interpolant, slowing the inner rasterization loop), so that
|
||||
not only would the world still be less than totally solid, because of
|
||||
the limitations of Gouraud shading, but the engine would also be too
|
||||
slow to support the complex worlds we had hoped for in Quake.
|
||||
|
||||
### The Quest for Alternative Lighting {#Heading7}
|
||||
|
||||
None of which is to say that Gouraud shading isn’t useful in general.
|
||||
Descent uses it to excellent effect, and in fact Quake uses Gouraud
|
||||
shading for moving entities, because these consist of small triangles
|
||||
and are always in motion, which helps hide the relatively small lighting
|
||||
errors. However, Gouraud shading didn’t seem capable of meeting our
|
||||
design goals for rendering quality and speed for drawing the world as a
|
||||
whole, so it was time to look for alternatives.
|
||||
|
||||
There are many alternative lighting approaches, most of them
|
||||
higher-quality than Gouraud, starting with Phong shading, in which the
|
||||
surface normal is interpolated across the polygon’s surface, and going
|
||||
all the way up to ray-tracing lighting techniques in which full
|
||||
illumination calculations are performed for all direct and reflected
|
||||
paths from each light source for each pixel. What all these approaches
|
||||
have in common is that they’re slower than Gouraud shading, too slow for
|
||||
our purposes in Quake. For weeks, we kicked around and rejected various
|
||||
possibilities and continued working with Gouraud shading for lack of a
|
||||
better alternative—until the day John came into work and said, “You
|
||||
know, I have an idea....”
|
||||
|
||||
#### Decoupling Lighting from Rasterization {#Heading8}
|
||||
|
||||
John’s idea came to him while was looking at a wall that had been carved
|
||||
into several pieces because of a spotlight, with an ugly lighting glitch
|
||||
due to a t-junction. He thought to himself that if only there were some
|
||||
way to treat it as one surface, it would look better and draw faster—and
|
||||
then he realized that there was a way to do that.
|
||||
|
||||
The insight was to split lighting and rasterization into two separate
|
||||
steps. In a normal Gouraud-based rasterizer, there’s first an off-line
|
||||
preprocessing step when the world database is built, during which
|
||||
polygons are added to support additional lighting detail as needed, and
|
||||
lighting values are calculated at the vertices of all polygons. At
|
||||
runtime, the lighting values are modified if dynamic lighting is
|
||||
required, and then the polygons are drawn with Gouraud shading.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](68-01.html) [Table of Contents](index.html) [Next](68-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue