📄 chapter07.html
字号:
</TABLE>
<BR>
<H3>
Antialiasing Points or Lines</H3>
To antialias points or lines, you need to turn on antialiasing with <B>glEnable()</B>,
passing in GL_POINT_SMOOTH or GL_LINE_SMOOTH, as appropriate. You might
also want to provide a quality hint with <B>glHint()</B>. (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.
<H4>
In RGBA Mode</H4>
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.
<P><B>Example 7-3 : </B>An Antialiased Wireframe Icosahedron: anti.c
<PRE>#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);
}</PRE>
<H4>
In Color-Index Mode</H4>
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.
<P><B>Example 7-4 : </B>Antialiasing in Color-Index Mode: antiindex.c
<PRE>#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);
}</PRE>
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.
<P><B>Advanced</B>
<P>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.
<H4>
Try This</H4>
Try This
<UL>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.</UL>
<H3>
Antialiasing Polygons</H3>
Antialiasing the edges of filled polygons is similar to antialiasing points
and lines. When different polygons have overlapping edges, you need to
blend the color values appropriately. You can either use the method described
in this section, or you can use the accumulation buffer to perform antialiasing
for your entire scene. Using the accumulation buffer, which is described
in Chapter 10 , is easier from your point of view, but it's much more computation-intensive
and therefore slower. However, as you'll see, the method described here
is rather cumbersome
<P>If you draw your polygons as points at the vertices or as outlines -
that is, by passing GL_POINT or GL_LINE to <B>glPolygonMode()</B> - point
or line antialiasing is applied, if enabled as described earlier. The rest
of this section addresses polygon antialiasing when you're using GL_FILL
as the polygon mode.
<P>In theory, you can antialias polygons in either RGBA or color-index
mode. However, object intersections affect polygon antialiasing more than
they affect point or line antialiasing, so rendering order and blending
accuracy become more critical. In fact, they're so critical that if you're
antialiasing more than one polygon, you need to order the polygons from
front to back and then use <B>glBlendFunc()</B> with GL_SRC_ALPHA_SATURATE
for the source factor and GL_ONE for the destination factor. Thus, antialiasing
polygons in color-index mode normally isn't practical.
<P>To antialias polygons in RGBA mode, you use the alpha value to represent
coverage values of polygon edges. You need to enable polygon antialiasing
by passing GL_POLYGON_SMOOTH to <B>glEnable()</B>. This causes pixels on
the edges of the polygon to be assigned fractional alpha values based on
their coverage, as though they were lines being antialiased. Also, if you
desire, you can supply a value for GL_POLYGON_SMOOTH_HINT.
<P>Now you need to blend overlapping edges appropriately. First, turn off
the depth buffer so that you have control over how overlapping pixels are
drawn. Then set the blending factors to GL_SRC_ALPHA_SATURATE (source)
and GL_ONE (destination). With this specialized blending function, the
final color is the sum of the destination color and the scaled source color;
the scale factor is the smaller of either the incoming source alpha value
or one minus the destination alpha value. This means that for a pixel with
a large alpha value, successive incoming pixels have little effect on the
final color because one minus the destination alpha is almost zero. With
this method, a pixel on the edge of a polygon might be blended eventually
with the colors from another polygon that's drawn later. Finally, you need
to sort all the polygons in your scene so that they're ordered from front
to back before drawing them.
<P>Example 7-5 shows how to antialias filled polygons; clicking the left
mouse button toggles the antialiasing on and off. Note that backward-facing
polygons are culled and that the alpha values in the color buffer are cleared
to zero before any drawing. (Your color buffer must store alpha values
for this technique to work correctly.)
<P><B>Example 7-5 : </B>Antialiasing Filled Polygons: antipoly.c
<PRE>#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
GLboolean polySmooth;
void myinit(void)
{
GLfloat mat_ambient[] = { 0.0, 0.0, 0.0, 1.00 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.00 };
GLfloat mat_shininess[] = { 15.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_BLEND);
glCullFace (GL_BACK);
glEnable (GL_CULL_FACE);
glEnable (GL_POLYGON_SMOOTH);
polySmooth = GL_TRUE;
glClearColor (0.0, 0.0, 0.0, 0.0);
}
void toggleSmooth (AUX_EVENTREC *event)
{
if (polySmooth) {
polySmooth = GL_FALSE;
glDisable (GL_BLEND);
glDisable (GL_POLYGON_SMOOTH);
glEnable (GL_DEPTH_TEST);
}
else {
polySmooth = GL_TRUE;
glEnable (GL_BLEND);
glEnable (GL_POLYGON_SMOOTH);
glDisable (GL_DEPTH_TEST);
}
}
void display(void)
{
GLfloat position[] = { 0.0, 0.0, 1.0, 0.0 };
GLfloat mat_cube1[] = { 0.75, 0.75, 0.0, 1.0 };
GLfloat mat_cube2[] = { 0.0, 0.75, 0.75, 1.0 };
if (polySmooth)
glClear (GL_COLOR_BUFFER_BIT);
else
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix ();
glTranslatef (0.0, 0.0, -8.0);
glLightfv (GL_LIGHT0, GL_POSITION, position);
glBlendFunc (GL_SRC_ALPHA_SATURATE, GL_ONE);
glPushMatrix ();
glRotatef (30.0, 1.0, 0.0, 0.0);
glRotatef (60.0, 0.0, 1.0, 0.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_cube1);
auxSolidCube (1.0, 1.0, 1.0);
glPopMatrix ();
glTranslatef (0.0, 0.0, -2.0);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_cube2);
glRotatef (30.0, 0.0, 1.0, 0.0);
glRotatef (60.0, 1.0, 0.0, 0.0);
auxSolidCube (1.0);
glPopMatrix ();
glFlush ();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -