136 lines
7.4 KiB
Markdown
136 lines
7.4 KiB
Markdown
---
|
|
title: Michael Abrash's Graphics Programming Black Book, Special Edition
|
|
author: Michael Abrash
|
|
date: '1997-07-01'
|
|
isbn: '1576101746'
|
|
publisher: The Coriolis Group
|
|
category: 'Web and Software Development: Game Development,Web and Software Development:
|
|
Graphics and Multimedia Development'
|
|
chapter: '57'
|
|
pages: 1061-1065
|
|
---
|
|
|
|
## Chapter 57\
|
|
10,000 Freshly Sheared Sheep on the Screen {#Heading1}
|
|
|
|
### The Critical Role of Experience in Implementing Fast, Smooth Texture Mapping {#Heading2}
|
|
|
|
I recently spent an hour or so learning how to shear a sheep. Among
|
|
other things, I learned—in great detail—about the importance of
|
|
selecting the proper comb for your shears, heard about the man who holds
|
|
the world's record for sheep sheared in a day (more than 600, if memory
|
|
serves), and discovered, Lord help me, the many and varied ways in which
|
|
the New Zealand Sheep Shearing Board improves the approved
|
|
sheep-shearing method every year. The fellow giving the presentation did
|
|
his best, but let's face it, sheep just aren't very interesting. If you
|
|
have children, you'll know why I was there; if you don't, there's no use
|
|
explaining.
|
|
|
|
The chap doing the shearing did say one thing that stuck with me,
|
|
although it may not sound particularly profound. (Actually, it sounds
|
|
pretty silly, but bear with me.) He said, "You don't get really good at
|
|
sheep shearing for 10 years, or 10,000 sheep." I'll buy that. In fact,
|
|
to extend that morsel of wisdom to the greater, non-ovine-centric
|
|
universe, it actually takes a good chunk of experience before you get
|
|
good at anything worthwhile—especially graphics, for a couple of
|
|
reasons. First, performance matters a lot in graphics, and performance
|
|
programming is largely a matter of experience. You can't speed up PC
|
|
graphics simply by looking in a book for a better algorithm; you have to
|
|
understand the code C compilers generate, assembly language
|
|
optimization, VGA hardware, and the performance implications of various
|
|
graphics-programming approaches and algorithms. Second, computer
|
|
graphics is a matter of illusion, of convincing the eye to see what you
|
|
want it to see, and that's very much a black art based on experience.
|
|
|
|
#### Visual Quality: A Black Hole ... Er, Art {#Heading3}
|
|
|
|
Pleasing the eye with realtime computer animation is something less than
|
|
a science, at least at the PC level, where there's a limited color
|
|
palette and no time for antialiasing; in fact, sometimes it can be more
|
|
than a little frustrating. As you may recall, in the previous chapter I
|
|
implemented texture mapping in X-Sharp. There was plenty of experience
|
|
involved there, some of which I didn't mention. My first implementation
|
|
was disappointing; the texture maps shimmied and sheared badly, like a
|
|
loosely affiliated flock of pixels, each marching to its own drummer.
|
|
Then, I added a control key to speed up the rotation; what a difference!
|
|
The aliasing problems were still there, but with the faster rotation,
|
|
the pixels moved too quickly for the eye to pick up on the aliasing; the
|
|
rotating texture maps, and the rotating ball as a whole, crossed the
|
|
threshold into being accepted by the eye as a viewed object, rather than
|
|
simply a collection of pixels.
|
|
|
|
The obvious lesson here is that adequate speed is important to
|
|
convincing animation. There's another, less obvious side to this lesson,
|
|
though. I'd been running the texture-mapping demo on a 20 MHz 386 with a
|
|
slow VGA when I discovered the beneficial effects of greater animation
|
|
speed. When, some time later, I ran the demo on a 33 MHz 486 with a fast
|
|
VGA, I found that the faster rotation was too fast! The ball spun so
|
|
rapidly that the eye couldn't blend successive images together into
|
|
continuous motion, much like watching a badly flickering movie.
|
|
|
|
> 
|
|
> So the second lesson is that either too little or too much speed can
|
|
> destroy the illusion. Unless you're antialiasing, you need to tune the
|
|
> shifting of your images so that they're in the "sweet spot" of apparent
|
|
> motion, in which the eye is willing to ignore the jumping and aliasing,
|
|
> and blend the images together into continuous motion. Only experience
|
|
> can give you a feel for that sweet spot.
|
|
|
|
#### Fixed-Point Arithmetic, Redux {#Heading4}
|
|
|
|
In the previous chapter I added texture mapping to X-Sharp, but lacked
|
|
space to explain some of its finer points. I'll pick up the thread now
|
|
and cover some of those points here, and discuss the visual and
|
|
performance enhancements that previous chapter's code needed—and which
|
|
are now present in the version of X-Sharp in this chapter's subdirectory
|
|
on the CD-ROM.
|
|
|
|
Back in Chapter 38, I spent a good bit of time explaining exactly which
|
|
pixels were inside a polygon and which were outside, and how to draw
|
|
those pixels accordingly. This was important, I said, because only with
|
|
a precise, consistent way of defining inside and outside would it be
|
|
possible to draw adjacent polygons without either overlap or gaps
|
|
between them.
|
|
|
|
As a corollary, I added that only an all-integer, edge-stepping approach
|
|
would do for polygon filling. Fixed-point arithmetic, although alluring
|
|
for speed and ease of use, would be unacceptable because round-off error
|
|
would result in imprecise pixel placement.
|
|
|
|
More than a year then passed between the time I wrote that statement and
|
|
the time I implemented X-Sharp's texture mapper, during which time my
|
|
long-term memory apparently suffered at least partial failure. When I
|
|
went to implement texture mapping for the previous chapter, I decided
|
|
that since transformed destination vertices can fall at fractional pixel
|
|
locations, the cleanest way to do the texture mapping would be to use
|
|
fixed-point coordinates for both the source texture and the destination
|
|
screen polygon. That way, there would be a minimum of distortion as the
|
|
polygon rotated and moved. Theoretically, that made sense; but there was
|
|
one small problem: gaps between polygons.
|
|
|
|
Yes, folks, I had ignored the voice of experience (my own voice, at
|
|
that) at my own peril. You can be assured I will not forget this
|
|
particular lesson again: Fixed-point arithmetic is not precise. That's
|
|
not to say that it's impossible to use fixed-point for drawing polygons;
|
|
if all adjacent edges share common start and end vertices and common
|
|
edges are always stepped in the same direction, all polygons should
|
|
share the same fixed-point imprecision, and edges should fit properly
|
|
(although polygons may not include exactly the right pixels). What you
|
|
absolutely cannot do is mix fixed-point and all-integer polygon-filling
|
|
approaches when drawing, as shown in Figure 57.1. Consequently, I ended
|
|
up using an all-integer approach in X-Sharp for stepping through the
|
|
destination polygon. However, I kept the fixed-point approach, which is
|
|
faster and much simpler, for stepping through the source.
|
|
|
|
Why was it all right to mix approaches in this case? Precise pixel
|
|
placement only matters when drawing; otherwise, we can get gaps, which
|
|
are very visible. When selecting a pixel to copy from the source
|
|
texture, however, the worst that happens is that we pick the source
|
|
pixel next to the one we really want, causing the mapped texture to
|
|
appear to have shifted by one pixel at the corresponding destination
|
|
pixel; given all the aliasing and shearing already going on in the
|
|
texture-mapping process, a one-pixel mapping error is insignificant.
|
|
|
|
Experience again: It's the difference between knowing which flaws (like
|
|
small texture shifts) can reasonably be ignored, and which (like those
|
|
that produce gaps between polygons) must be avoided at all costs.
|