133 lines
5.6 KiB
Markdown
133 lines
5.6 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](55-01.html) [Table of Contents](index.html) [Next](55-03.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
So it’s perfectly reasonable to maintain 24 bits of color resolution,
|
||
and X-Sharp represents colors internally as ideal, device-independent
|
||
24-bit RGB triplets. All shading calculations are performed on these
|
||
triplets, with 24-bit color precision. It’s only after the final 24-bit
|
||
RGB drawing color is calculated that the display adapter’s color
|
||
capabilities come into play, as the X-Sharp function
|
||
**ModelColorToColorIndex()** is called to map the desired RGB color to
|
||
the closest match the adapter is capable of displaying. Of course, that
|
||
mapping is adapter-dependent. On a 24-bpp device, it’s pretty obvious
|
||
how the internal RGB color format maps to displayed pixel colors:
|
||
directly. On VGAs with 15-bpp Sierra Hicolor DACS, the mapping is
|
||
equally simple, with the five upper bits of each color component mapping
|
||
straight to display pixels. But how on earth do we map those
|
||
16,000,000-plus RGB colors into the 256-color space of a standard VGA?
|
||
|
||
This is the “color definition” problem I mentioned at the start of this
|
||
chapter. The VGA palette is arbitrarily programmable to any set of 256
|
||
colors, with each color defined by six bits each of red, green, and blue
|
||
intensity. In X-Sharp, the function **InitializePalette()** can be
|
||
customized to set up the palette however we wish; this gives us nearly
|
||
complete flexibility in defining the working color set. Even with
|
||
infinite flexibility, however, 256 out of 16,000,000 or so possible
|
||
colors is a pretty puny selection. It’s easy to set up the palette to
|
||
give yourself a good selection of just blue intensities, or of just
|
||
greens; but for general color modeling there’s simply not enough palette
|
||
to go around.
|
||
|
||
One way to deal with the limited simultaneous color capabilities of the
|
||
VGA is to build an application that uses only a subset of RGB space,
|
||
then bias the VGA’s palette toward that subspace. This is the approach
|
||
used in the DEMO1 sample program in X-Sharp; Listings 55.2 and 55.3 show
|
||
the versions of **InitializePalette()** and **ModelColorToColorIndex()**
|
||
that set up and perform the color mapping for DEMO1.
|
||
|
||
**LISTING 55.2 L55-2.C**
|
||
|
||
/* Sets up the palette in mode X, to a 2-2-2 general R-G-B organization, with
|
||
64 separate levels each of pure red, green, and blue. This is very good
|
||
for pure colors, but mediocre at best for mixes.
|
||
|
||
------------------------
|
||
|0 0 | Red|Green| Blue |
|
||
------------------------
|
||
7 6 5 4 3 2 1 0
|
||
|
||
------------------------
|
||
|0 1 | Red |
|
||
------------------------
|
||
7 6 5 4 3 2 1 0
|
||
|
||
------------------------
|
||
|1 0 | Green |
|
||
------------------------
|
||
7 6 5 4 3 2 1 0
|
||
|
||
------------------------
|
||
|1 1 | Blue |
|
||
------------------------
|
||
7 6 5 4 3 2 1 0
|
||
|
||
Colors are gamma corrected for a gamma of 2.3 to provide approximately
|
||
even intensity steps on the screen.
|
||
*/
|
||
|
||
#include <dos.h>
|
||
#include "polygon.h"
|
||
|
||
static unsigned char Gamma4Levels[] = { 0, 39, 53, 63 };
|
||
static unsigned char Gamma64Levels[] = {
|
||
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,
|
||
};
|
||
|
||
static unsigned char PaletteBlock[256][3]; /* 256 RGB entries */
|
||
|
||
void InitializePalette()
|
||
{
|
||
int Red, Green, Blue, Index;
|
||
union REGS regset;
|
||
struct SREGS sregset;
|
||
|
||
for (Red=0; Red<4; Red++) {
|
||
for (Green=0; Green<4; Green++) {
|
||
for (Blue=0; Blue<4; Blue++) {
|
||
Index = (Red<<4)+(Green<<2)+Blue;
|
||
PaletteBlock[Index][0] = Gamma4Levels[Red];
|
||
PaletteBlock[Index][1] = Gamma4Levels[Green];
|
||
PaletteBlock[Index][2] = Gamma4Levels[Blue];
|
||
}
|
||
}
|
||
}
|
||
|
||
for (Red=0; Red<64; Red++) {
|
||
PaletteBlock[64+Red][0] = Gamma64Levels[Red];
|
||
PaletteBlock[64+Red][1] = 0;
|
||
PaletteBlock[64+Red][2] = 0;
|
||
}
|
||
|
||
for (Green=0; Green<64; Green++) {
|
||
PaletteBlock[128+Green][0] = 0;
|
||
PaletteBlock[128+Green][1] = Gamma64Levels[Green];
|
||
PaletteBlock[128+Green][2] = 0;
|
||
}
|
||
|
||
for (Blue=0; Blue<64; Blue++) {
|
||
PaletteBlock[192+Blue][0] = 0;
|
||
PaletteBlock[192+Blue][1] = 0;
|
||
PaletteBlock[192+Blue][2] = Gamma64Levels[Blue];
|
||
}
|
||
|
||
/* Now set up the palette */
|
||
regset.x.ax = 0x1012; /* set block of DAC registers function */
|
||
regset.x.bx = 0; /* first DAC location to load */
|
||
regset.x.cx = 256; /* # 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, ®set, ®set, &sregset); /* load the palette block */
|
||
}
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](55-01.html) [Table of Contents](index.html) [Next](55-03.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|