#include <gl/gl.h> #include <gl/device.h> #include <stdlib.h> #include <math.h>
/* * This program illustrates the drawing of antialiased lines, of * a single (foreground) color, on an arbitrary multicolored * background. * * Note that this style of drawing is limited to precisely one * foreground color. * The number of background colors is also limited; the maximum * number of background colors is one-sixteenth of the total * number of colormap entries. * * The basic idea behind the algorithm is to divide the available * bitplanes into two groups: those containing the background * image, and those containing the anti-aliasing coverage * information. A color-ramp is loaded in the color map ranges * corresponding to the coverage information. The background * image colors can be arbitrary. * * Note that proper gamma correction is absolutely vital to * getting antialiased lines that look truly smooth to the user. * The gamma exponent depends on the monitor (specifically, on the * type of phosphors) and therefore needs to be tuned to the model * of the monitor. */
draw_fan()
{
int i; /* draw fan */
for (i=0; i<= 90; i+=10) {
pushmatrix();
rot (-(float) i, 'z');
move (0.0, 0.0, 0.0);
draw (0.0, 300.0, 0.0);
popmatrix();
}
}
#define AABLACK 0 #define AAGREEN 16 #define AARED 32 #define AAPURPLE 48 #define AAWHITE 64
/* experimentally determined gamma factor */ double gammy = 2.4;
/* a utility macro used to build the color ramp */
#define ADD_TO_RAMP(COL) \
{ \
for (j=0; j<16; j++) { \
col_idx = COL + j; \
rramp[col_idx] = (j*foreground_r + (16-j)*background_r) / 16; \
gramp[col_idx] = (j*foreground_g + (16-j)*background_g) / 16; \
bramp[col_idx] = (j*foreground_b + (16-j)*background_b) / 16; \
rramp[col_idx] = (int) \
(255.0 * pow (((double) rramp[col_idx])/255.0 , 1.0 / gammy)); \
gramp[col_idx] = (int) \
(255.0 * pow (((double) gramp[col_idx])/255.0 , 1.0 / gammy)); \
bramp[col_idx] = (int) \
(255.0 * pow (((double) bramp[col_idx])/255.0 , 1.0 / gammy)); \
} \
}
/* this routine creates an "random" color ramp and loads it */
void load_foreground_cmap (short foreground_r,
short foreground_g,
short foreground_b)
{
int i, j, col_idx;
int background_r, background_g, background_b;
short rramp[256], gramp[256], bramp[256];
/* update gamma correction factor */ if (getbutton (WKEY)) gammy +=0.02; if (getbutton (SKEY)) gammy -=0.02;
/* create color ramp */ /* AABLACK */ background_r = 0; background_g = 0; background_b = 0; ADD_TO_RAMP (AABLACK); /* AAGREEN */ background_r = 0; background_g = 255; background_b = 0; ADD_TO_RAMP (AAGREEN); /* AARED */ background_r = 255; background_g = 127; background_b = 0; ADD_TO_RAMP (AARED); /* AAPURPLE */ background_r = 150; background_g = 25; background_b = 120; ADD_TO_RAMP (AAPURPLE); /* AAWHITE */ background_r = 225; background_g = 235; background_b = 255; ADD_TO_RAMP (AAWHITE); mapcolors (0, 127, rramp, gramp, bramp); }
#define RRRANDO ( (float) (400*rand()/32767));
/* This routine draws a background of random polygons.
* One of five colors are selected randomly. */
void draw_background() {
float vv[2];
int i, j;
srand (234515);
color (AABLACK);
clear();
/* the writemask guarentees that drawing is occuring only
* into the "background" bitplanes */
writemask (0xf0);
for (j=0; j<12; j++) {
color (16*(5*rand()/32767));
bgnpolygon();
for (i=0; i<6; i++) {
vv[0] = RRRANDO;
vv[1] = RRRANDO;
v2f (vv);
}
endpolygon(); }
}
main ()
{
int i, j, k, iinc=1, jinc=3, kinc=7;
prefsize (400.0, 400.0);
winopen ("antialiased lines");
cmode();
doublebuffer();
gconfig();
save_cmap();
/* create the color ramp --- the foreground color will be white */
load_foreground_cmap (255, 255, 255);
/* draw the random background */
draw_background();
swapbuffers ();
draw_background();
/* the writemask write-protects the background while the lines
* are being drawn */
writemask (0x0f);
/* loop until the right mouse button is depressed */
while (!getbutton(RIGHTMOUSE) && !getbutton(ESCKEY)) {
color (0);
clear ();
pushmatrix();
/* draw normal, jaggy lines */
linesmooth(FALSE);
color (15);
pushmatrix();
translate (10.0, 10.0, 0.0);
rotate( 500-getvaluator (MOUSEY), 'z');
draw_fan();
popmatrix();
/* draw smooth, anti-aliased lines */
linesmooth(TRUE);
pushmatrix();
translate (390.0, 30.0, 0.0);
rotate( getvaluator (MOUSEY) + 400, 'z');
draw_fan();
popmatrix();
popmatrix();
swapbuffers();
/* cycle through a random set of foreground colors */
i+=iinc;
j+=jinc;
k+=kinc;
if ((i+iinc>5*255) || (i+iinc<0)) {
iinc = -iinc;
i+=iinc;
}
if ((j+jinc>5*255) || (j+jinc<0)) {
jinc = -jinc;
j+=jinc;
}
if ((k+kinc>5*255) || (k+kinc<0)) {
kinc = -kinc;
k+=kinc;
}
if ( i%5 == 0) {
load_foreground_cmap ( (i/5)%255, (j/5)%255, (k/5)%255);
}
}
restore_cmap();
}
/*This saves the colormap*/ #define lo_end 0 #define hi_end 255 short *CarrayR, *CarrayG, *CarrayB;
save_cmap()
{
CarrayR = calloc (lo_end+hi_end,sizeof(short));
CarrayG = calloc (lo_end+hi_end,sizeof(short));
CarrayB = calloc (lo_end+hi_end,sizeof(short));
getmcolors ((Int16 const)lo_end,(Int16 const)hi_end,
CarrayR, CarrayG, CarrayB);
}
/*This restores the colormap*/
restore_cmap()
{
mapcolors ((Int16 const)lo_end,(Int16 const)hi_end,
CarrayR, CarrayG, CarrayB);
}
/*
Changes:
- Added the restoring of the colormap
- Added escape key and right mouse for clean exit
*/
The linesmooth subroutine.
Pixel Coverage in GL3.2 Version 4 for AIX: Programming Concepts.