230 lines
9.3 KiB
HTML
230 lines
9.3 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Wu'ed in Haste; Fried, Stewed at Leisure</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=42//-->
|
|
<!--PAGES=782-784//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="42-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="42-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<H3><A NAME="Heading5"></A><FONT COLOR="#000077">Sample Wu Antialiasing</FONT></H3>
|
|
<P>The true test of any antialiasing technique is how good it looks, so let’s have a look at Wu antialiasing in action. Listing 42.1 is a C implementation of Wu antialiasing. Listing 42.2 is a sample program that draws a variety of Wu-antialiased lines, followed by non-antialiased lines, for comparison. Listing 42.3 contains <B>DrawPixel()</B> and <B>SetMode()</B> functions for mode 13H, the VGA’s 320×200 256-color mode. Finally, Listing 42.4 is a simple, non-antialiased line-drawing routine. Link these four listings together and run the resulting program to see both Wu-antialiased and non-antialiased lines.</P>
|
|
<P><B>LISTING 42.2 L42-2.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* Sample line-drawing program to demonstrate Wu antialiasing. Also draws
|
|
* non-antialiased lines for comparison.
|
|
* Tested with Borland C++ in C compilation mode and the small model.
|
|
*/
|
|
#include <dos.h>
|
|
#include <conio.h>
|
|
|
|
void SetPalette(struct WuColor *);
|
|
extern void DrawWuLine(int, int, int, int, int, int, unsigned int);
|
|
extern void DrawLine(int, int, int, int, int);
|
|
extern void SetMode(void);
|
|
extern int ScreenWidthInPixels; /* screen dimension globals */
|
|
extern int ScreenHeightInPixels;
|
|
|
|
#define NUM_WU_COLORS 2 /* # of colors we'll do antialiased drawing with */
|
|
struct WuColor { /* describes one color used for antialiasing */
|
|
int BaseColor; /* # of start of palette intensity block in DAC */
|
|
int NumLevels; /* # of intensity levels */
|
|
int IntensityBits; /* IntensityBits == log2 NumLevels */
|
|
int MaxRed; /* red component of color at full intensity */
|
|
int MaxGreen; /* green component of color at full intensity */
|
|
int MaxBlue; /* blue component of color at full intensity */
|
|
};
|
|
enum {WU_BLUE=0, WU_WHITE=1}; /* drawing colors */
|
|
struct WuColor WuColors[NUM_WU_COLORS] = /* blue and white */
|
|
{{192, 32, 5, 0, 0, 0x3F}, {224, 32, 5, 0x3F, 0x3F, 0x3F}};
|
|
|
|
void main()
|
|
{
|
|
int CurrentColor, i;
|
|
union REGS regset;
|
|
|
|
/* Draw Wu-antialiased lines in all directions */
|
|
SetMode();
|
|
SetPalette(WuColors);
|
|
for (i=5; i<ScreenWidthInPixels; i += 10) {
|
|
DrawWuLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10+i/5,
|
|
ScreenHeightInPixels/5, i, ScreenHeightInPixels-1,
|
|
WuColors[WU_BLUE].BaseColor, WuColors[WU_BLUE].NumLevels,
|
|
WuColors[WU_BLUE].IntensityBits);
|
|
}
|
|
for (i=0; i<ScreenHeightInPixels; i += 10) {
|
|
DrawWuLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10, i/5, 0, i,
|
|
WuColors[WU_BLUE].BaseColor, WuColors[WU_BLUE].NumLevels,
|
|
WuColors[WU_BLUE].IntensityBits);
|
|
}
|
|
for (i=0; i<ScreenHeightInPixels; i += 10) {
|
|
DrawWuLine(ScreenWidthInPixels/2+ScreenWidthInPixels/10, i/5,
|
|
ScreenWidthInPixels-1, i, WuColors[WU_BLUE].BaseColor,
|
|
WuColors[WU_BLUE].NumLevels, WuColors[WU_BLUE].IntensityBits);
|
|
}
|
|
for (i=0; i<ScreenWidthInPixels; i += 10) {
|
|
DrawWuLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10+i/5,
|
|
ScreenHeightInPixels, i, 0, WuColors[WU_WHITE].BaseColor,
|
|
WuColors[WU_WHITE].NumLevels,
|
|
WuColors[WU_WHITE].IntensityBits);
|
|
}
|
|
getch(); /* wait for a key press */
|
|
|
|
/* Now clear the screen and draw non-antialiased lines */
|
|
SetMode();
|
|
SetPalette(WuColors);
|
|
for (i=0; i<ScreenWidthInPixels; i += 10) {
|
|
DrawLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10+i/5,
|
|
ScreenHeightInPixels/5, i, ScreenHeightInPixels-1,
|
|
WuColors[WU_BLUE].BaseColor);
|
|
}
|
|
for (i=0; i<ScreenHeightInPixels; i += 10) {
|
|
DrawLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10, i/5, 0, i,
|
|
WuColors[WU_BLUE].BaseColor);
|
|
}
|
|
for (i=0; i<ScreenHeightInPixels; i += 10) {
|
|
DrawLine(ScreenWidthInPixels/2+ScreenWidthInPixels/10, i/5,
|
|
ScreenWidthInPixels-1, i, WuColors[WU_BLUE].BaseColor);
|
|
}
|
|
for (i=0; i<ScreenWidthInPixels; i += 10) {
|
|
DrawLine(ScreenWidthInPixels/2-ScreenWidthInPixels/10+i/5,
|
|
ScreenHeightInPixels, i, 0, WuColors[WU_WHITE].BaseColor);
|
|
}
|
|
getch(); /* wait for a key press */
|
|
|
|
regset.x.ax = 0x0003; /* AL = 3 selects 80x25 text mode */
|
|
int86(0x10, &regset, &regset); /* return to text mode */
|
|
}
|
|
|
|
/* Sets up the palette for antialiasing with the specified colors.
|
|
* Intensity steps for each color are scaled from the full desired intensity
|
|
* of the red, green, and blue components for that color down to 0%
|
|
* intensity; each step is rounded to the nearest integer. Colors are
|
|
* corrected for a gamma of 2.3. The values that the palette is programmed
|
|
* with are hardwired for the VGA's 6 bit per color DAC.
|
|
*/
|
|
void SetPalette(struct WuColor * WColors)
|
|
{
|
|
int i, j;
|
|
union REGS regset;
|
|
struct SREGS sregset;
|
|
static unsigned char PaletteBlock[256][3]; /* 256 RGB entries */
|
|
/* Gamma-corrected DAC color components for 64 linear levels from 0% to
|
|
100% intensity */
|
|
static unsigned char GammaTable[] = {
|
|
0, 10, 14, 17, 19, 21, 23, 24, 26, 27, 28, 29, 31, 32, 33, 34,
|
|
35, 36, 37, 37, 38, 39, 40, 41, 41, 42, 43, 44, 44, 45, 46, 46,
|
|
47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55,
|
|
56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63};
|
|
|
|
for (i=0; i<NUM_WU_COLORS; i++) {
|
|
for (j=0; j<WColors[i].NumLevels; j++) {
|
|
PaletteBlock[j][0] = GammaTable[((double)WColors[i].MaxRed * (1.0 -
|
|
(double)j / (double)(WColors[i].NumLevels - 1))) + 0.5];
|
|
PaletteBlock[j][1] = GammaTable[((double)WColors[i].MaxGreen * (1.0 -
|
|
(double)j / (double)(WColors[i].NumLevels - 1))) + 0.5];
|
|
PaletteBlock[j][2] = GammaTable[((double)WColors[i].MaxBlue * (1.0 -
|
|
(double)j / (double)(WColors[i].NumLevels - 1))) + 0.5];
|
|
}
|
|
/* Now set up the palette to do Wu antialiasing for this color */
|
|
regset.x.ax = 0x1012; /* set block of DAC registers function */
|
|
regset.x.bx = WColors[i].BaseColor; /* first DAC location to load */
|
|
regset.x.cx = WColors[i].NumLevels; /* # of DAC locations to load */
|
|
regset.x.dx = (unsigned int)PaletteBlock; /* offset of array from which
|
|
to load RGB settings */
|
|
sregset.es = _DS; /* segment of array from which to load settings */
|
|
int86x(0x10, &regset, &regset, &sregset); /* load the palette block */
|
|
}
|
|
}
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><B>LISTING 42.3 L42-3.C</B></P>
|
|
<!-- CODE //-->
|
|
<PRE>
|
|
/* VGA mode 13h pixel-drawing and mode set functions.
|
|
* Tested with Borland C++ in C compilation mode and the small model.
|
|
*/
|
|
#include <dos.h>
|
|
|
|
/* Screen dimension globals, used in main program to scale. */
|
|
int ScreenWidthInPixels = 320;
|
|
int ScreenHeightInPixels = 200;
|
|
|
|
/* Mode 13h draw pixel function. */
|
|
void DrawPixel(int X, int Y, int Color)
|
|
{
|
|
#define SCREEN_SEGMENT 0xA000
|
|
unsigned char far *ScreenPtr;
|
|
|
|
FP_SEG(ScreenPtr) = SCREEN_SEGMENT;
|
|
FP_OFF(ScreenPtr) = (unsigned int) Y * ScreenWidthInPixels + X;
|
|
*ScreenPtr = Color;
|
|
}
|
|
|
|
/* Mode 13h mode-set function. */
|
|
void SetMode()
|
|
{
|
|
union REGS regset;
|
|
|
|
/* Set to 320x200 256-color graphics mode */
|
|
regset.x.ax = 0x0013;
|
|
int86(0x10, &regset, &regset);
|
|
}
|
|
</PRE>
|
|
<!-- END CODE //-->
|
|
<P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="42-02.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="42-04.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|