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

121 lines
7.9 KiB
Markdown

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.
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
![](images/i.jpg) *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.