To antialias points or lines, you need to turn on antialiasing with glEnable(), passing in GL_POINT_SMOOTH or GL_LINE_SMOOTH, as appropriate. You might also want to provide a quality hint with glHint(). (Remember that you can set the size of a point or the width of a line. You can also stipple a line. See Chapter 2 .) Next, follow the procedures described in one of the following sections, depending on whether you're in RGBA or color-index mode.
In RGBA mode, you need to enable blending. The blending factors you most likely want to use are GL_SRC_ALPHA (source) and GL_ONE_MINUS_SRC_ALPHA (destination). Alternatively, you can use GL_ONE for the destination factor to make lines a little brighter where they intersect. Now you're ready to draw whatever points or lines you want antialiased. The antialiased effect is most noticeable if you use a fairly high alpha value. Remember that since you're performing blending, you might need to consider the rendering order as described in "Three-Dimensional Blending with the Depth Buffer" ; in most cases, however, the ordering can be ignored without significant adverse effects. Example 7-3 initializes the necessary modes for antialiasing and then draws a wireframe icosahedron. Note that the depth buffer isn't enabled in this example.
Example 7-3 : An Antialiased Wireframe Icosahedron: anti.c
#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
void myinit(void)
{
GLfloat values[2];
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, values);
printf("GL_LINE_WIDTH_GRANULARITY value is %3.1f\n",
values[0]);
glGetFloatv(GL_LINE_WIDTH_RANGE, values);
printf("GL_LINE_WIDTH_RANGE values are %3.1f %3.1f\n",
values[0], values[1]);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glLineWidth(1.5);
glShadeModel(GL_FLAT);
glClearColor(0.0, 0.0, 0.0, 0.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0, 1.0, 1.0, 1.0);
auxWireIcosahedron(1.0);
glFlush();
}
void myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat) w/(GLfloat) h, 3.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.0);
}
int main(int argc, char** argv)
{
auxInitDisplayMode(AUX_SINGLE | AUX_RGBA | AUX_DEPTH);
auxInitPosition(0, 0, 400, 400);
auxInitWindow(argv[0]);
myinit();
auxReshapeFunc(myReshape);
auxMainLoop(display);
}
The tricky part about antialiasing in color-index mode is loading and using the color map. Since the last 4 bits of the color index indicate the coverage value, you need to load sixteen contiguous indices with a color ramp from the background color to the object's color. (The ramp has to start with an index value that's a multiple of 16.) Then, you clear the color buffer to the first of the sixteen colors in the ramp and draw your points or lines using colors in the ramp. Example 7-4 demonstrates how to construct the color ramp to draw an antialiased wireframe icosahedron in color-index mode. In this example, the color ramp starts at index 32 and contains shades of gray.
Example 7-4 : Antialiasing in Color-Index Mode: antiindex.c
#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
#define RAMPSIZE 16
#define RAMPSTART 32
void myinit(void)
{
int i;
for (i = 0; i < RAMPSIZE; i++) {
GLfloat shade;
shade = (GLfloat) i/(GLfloat) RAMPSIZE;
auxSetOneColor(RAMPSTART+(GLint)i, shade, shade, shade);
}
glEnable (GL_LINE_SMOOTH);
glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
glLineWidth (1.5);
glClearIndex ((GLfloat) RAMPSTART);
glShadeModel(GL_FLAT);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glIndexi(RAMPSTART);
auxWireIcosahedron(1.0);
glFlush();
}
void myReshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective (45.0, (GLfloat) w/(GLfloat) h, 3.0, 5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -4.0);
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_INDEX | AUX_DEPTH);
auxInitPosition (0, 0, 400, 400);
auxInitWindow (argv[0]);
myinit();
auxReshapeFunc (myReshape);
auxMainLoop(display);
}Since the color ramp goes from the background color to the object's color, the antialiased object looks correct only when it's drawn on top of the background. If the antialiased object is drawn on top of another object, places where the objects intersect will have the wrong colors, unless you've constructed your color ramps taking this into consideration. To get the best result, use the depth buffer to ensure that the pixel colors correspond to the "nearest" objects. In RGBA mode, however, the colors of both objects are blended, so the results look more natural. Thus, you typically don't use the depth buffer when rendering a scene consisting of antialiased points and lines.
Advanced
The trick described in "Three-Dimensional Blending with the Depth Buffer" can also be used to mix antialiased points and lines with aliased, depth-buffered polygons. To do this, draw the polygons first, then make the depth buffer read-only and draw the points and lines. The points and lines will intersect nicely with each other but will be obscured by nearer polygons.
Try This
Take a previous program, such as the robot arm or solar system program described in "Examples of Composing Several Transformations" and draw wireframe objects with antialiasing. Try it with either RGBA or color-index mode. Also try different line widths or point sizes to see their effects.
OpenGL Programming Guide