📄 chapter02.html
字号:
glColor3f(0.0, 0.0, 1.0); /* blue */
glVertex(...);
glVertex(...);
glEnd();</PRE>
You can use any combination of the twenty-four versions of the <B>glVertex*()</B>
command between <B>glBegin()</B> and <B>glEnd()</B>, although in real applications
all the calls in any particular instance tend to be of the same form.
<P>
<HR>
<H2>
Displaying Points, Lines, and Polygons</H2>
By default, a point is drawn as a single pixel on the screen, a line is
drawn solid and one pixel wide, and polygons are drawn solidly filled in.
The following paragraphs discuss the details of how to change these default
display modes.
<H3>
Point Details</H3>
To control the size of a rendered point, use <B>glPointSize()</B> and supply
the desired size in pixels as the argument. void <B>glPointSize</B>(GLfloat
<I>size</I>);
<P>Sets the width in pixels for rendered points; <I>size</I> must be greater
than 0.0 and by default is 1.0.
<P>The actual collection of pixels on the screen that are drawn for various
point widths depends on whether antialiasing is enabled. (Antialiasing
is a technique for smoothing points and lines as they're rendered. This
topic is covered in detail in "Antialiasing." ) If antialiasing is disabled
(the default), fractional widths are rounded to integer widths, and a screen-aligned
square region of pixels is drawn. Thus, if the width is 1.0, the square
is one pixel by one pixel; if the width is 2.0, the square is two pixels
by two pixels, and so on.
<P>With antialiasing enabled, a circular group of pixels is drawn, and
the pixels on the boundaries are typically drawn at less than full intensity
to give the edge a smoother appearance. In this mode, nonintegral widths
aren't rounded.
<P>Most OpenGL implementations support very large point sizes. A particular
implementation, however, might limit the size of nonantialiased points
to its maximum antialiased point size, rounded to the nearest integer value.
You can obtain this floating-point value by using GL_POINT_SIZE_RANGE with
<B>glGetFloatv()</B>.
<H3>
Line Details</H3>
With OpenGL, you can specify lines with different widths and lines that
are <I>stippled</I> in various ways - dotted, dashed, drawn with alternating
dots and dashes, and so on.
<H4>
Wide Lines</H4>
void <B>glLineWidth</B>(GLfloat <I>width</I>);
<P>Sets the width in pixels for rendered lines; <I>width</I> must be greater
than 0.0 and by default is 1.0.
<P>The actual rendering of lines is affected by the antialiasing mode,
in the same way as for points. (See "Antialiasing." ) Without antialiasing,
widths of 1, 2, and 3 draw lines one, two, and three pixels wide. With
antialiasing enabled, nonintegral line widths are possible, and pixels
on the boundaries are typically partially filled. As with point sizes,
a particular OpenGL implementation might limit the width of nonantialiased
lines to its maximum antialiased line width, rounded to the nearest integer
value. You can obtain this floating-point value by using GL_LINE_WIDTH_RANGE
with <B>glGetFloatv()</B>.
<P>Keep in mind that by default lines are one pixel wide, so they appear
wider on lower-resolution screens. For computer displays, this isn't typically
an issue, but if you're using OpenGL to render to a high-resolution plotter,
one-pixel lines might be nearly invisible. To obtain resolution-independent
line widths, you need to take into account the physical dimensions of pixels.
<P><B>Advanced</B>
<P>With nonantialiased wide lines, the line width isn't measured perpendicular
to the line. Instead, it's measured in the <I>y</I> direction if the absolute
value of the slope is less than 1.0; otherwise, it's measured in the <I>x</I>
direction. The rendering of an antialiased line is exactly equivalent to
the rendering of a filled rectangle of the given width, centered on the
exact line. See "Polygon Details," for a discussion of the rendering of
filled polygonal regions.
<H4>
Stippled Lines</H4>
To make stippled (dotted or dashed) lines, you use the command <B>glLineStipple()</B>
to define the stipple pattern, and then you enable line stippling with
<B>glEnable()</B>:
<PRE>glLineStipple(1, 0x3F07);
glEnable(GL_LINE_STIPPLE);</PRE>
void <B>glLineStipple</B>(GLint <I>factor</I>, GLushort <I>pattern</I>);
<P>Sets the current stippling pattern for lines. The <I>pattern</I> argument
is a 16-bit series of 0s and 1s, and it's repeated as necessary to stipple
a given line. A 1 indicates that drawing occurs, and 0 that it does not,
on a pixel-by-pixel basis, beginning with the low-order bits of the pattern.
The pattern can be stretched out by using <I>factor</I>, which multiplies
each subseries of consecutive 1s and 0s. Thus, if three consecutive 1s
appear in the pattern, they're stretched to six if <I>factor</I> is 2.
<I>factor</I>
is clamped to lie between 1 and 255. Line stippling must be enabled by
passing GL_LINE_STIPPLE to <B>glEnable()</B>; it's disabled by passing
the same argument to <B>glDisable()</B>.
<P>With the preceding example and the pattern 0x3F07 (which translates
to 0011111100000111 in binary), a line would be drawn with 3 pixels on,
then 5 off, 6 on, and 2 off. (If this seems backward, remember that the
low-order bits are used first.) If <I>factor</I> had been 2, the pattern
would have been elongated: 6 pixels on, 10 off, 12 on, and 4 off. Figure
2-7 shows lines drawn with different patterns and repeat factors. If you
don't enable line stippling, drawing proceeds as if <I>pattern</I> were
0xFFFF and <I>factor</I> 1. (Use <B>glDisable()</B> with GL_LINE_STIPPLE
to disable stippling.) Note that stippling can be used in combination with
wide lines to produce wide stippled lines.
<P><IMG SRC="figures/fig2-7.gif" ALT="[IMAGE]" NOSAVE HEIGHT=172 WIDTH=519>
<P><B>Figure 2-7 : </B>Stippled Lines
<BR>
<BR>
<P>One way to think of the stippling is that as the line is being drawn,
the pattern is shifted by one bit each time a pixel is drawn (or <I>factor</I>
pixels are drawn, if <I>factor</I> isn't 1). When a series of connected
line segments is drawn between a single <B>glBegin()</B> and <B>glEnd()</B>,
the pattern continues to shift as one segment turns into the next. This
way, a stippling pattern continues across a series of connected line segments.
When <B>glEnd()</B> is executed, the pattern is reset, and - if more lines
are drawn before stippling is disabled - the stippling restarts at the
beginning of the pattern. If you're drawing lines with GL_LINES, the pattern
resets for each independent line.
<P>Example 2-1 illustrates the results of drawing with a couple of different
stipple patterns and line widths. It also illustrates what happens if the
lines are drawn as a series of individual segments instead of a single
connected line strip. The results of running the program appear in Figure
2-8 .
<P><IMG SRC="figures/lines.gif" ALT="[IMAGE]" NOSAVE HEIGHT=138 WIDTH=379>
<P><B>Figure 2-8 : </B>Wide Stippled Lines
<BR>
<BR>
<P><B>Example 2-1 : </B>Using Line Stipple Patterns: lines.c
<PRE>#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
#define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES); \
glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();
void myinit (void) {
/* background to be cleared to black */
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
int i;
glClear (GL_COLOR_BUFFER_BIT);
/* draw all lines in white */
glColor3f (1.0, 1.0, 1.0);
/* in 1st row, 3 lines, each with a different stipple */
glEnable (GL_LINE_STIPPLE);
glLineStipple (1, 0x0101); /* dotted */
drawOneLine (50.0, 125.0, 150.0, 125.0);
glLineStipple (1, 0x00FF); /* dashed */
drawOneLine (150.0, 125.0, 250.0, 125.0);
glLineStipple (1, 0x1C47); /* dash/dot/dash */
drawOneLine (250.0, 125.0, 350.0, 125.0);
/* in 2nd row, 3 wide lines, each with different stipple */
glLineWidth (5.0);
glLineStipple (1, 0x0101);
drawOneLine (50.0, 100.0, 150.0, 100.0);
glLineStipple (1, 0x00FF);
drawOneLine (150.0, 100.0, 250.0, 100.0);
glLineStipple (1, 0x1C47);
drawOneLine (250.0, 100.0, 350.0, 100.0);
glLineWidth (1.0);
/* in 3rd row, 6 lines, with dash/dot/dash stipple, */
/* as part of a single connected line strip */
glLineStipple (1, 0x1C47);
glBegin (GL_LINE_STRIP);
for (i = 0; i < 7; i++)
glVertex2f (50.0 + ((GLfloat) i * 50.0), 75.0);
glEnd ();
/* in 4th row, 6 independent lines, */
/* with dash/dot/dash stipple */
for (i = 0; i < 6; i++) {
drawOneLine (50.0 + ((GLfloat) i * 50.0),
50.0, 50.0 + ((GLfloat)(i+1) * 50.0), 50.0);
}
/* in 5th row, 1 line, with dash/dot/dash stipple */
/* and repeat factor of 5 */
glLineStipple (5, 0x1C47);
drawOneLine (50.0, 25.0, 350.0, 25.0);
glFlush ();
}
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
auxInitPosition (0, 0, 400, 150);
auxInitWindow (argv[0]);
myinit ();
auxMainLoop(display);
}</PRE>
<H3>
Polygon Details</H3>
Polygons are typically drawn by filling in all the pixels enclosed within
the boundary, but you can also draw them as outlined polygons, or simply
as points at the vertices. A filled polygon might be solidly filled, or
stippled with a certain pattern. Although the exact details are omitted
here, polygons are drawn in such a way that if adjacent polygons share
an edge or vertex, the pixels making up the edge or vertex are drawn exactly
once - they're included in only one of the polygons. This is done so that
partially transparent polygons don't have their edges drawn twice, which
would make those edges appear darker (or brighter, depending on what color
you're drawing with). Note that it might result in narrow polygons having
no filled pixels in one or more rows or columns of pixels. Antialiasing
polygons is more complicated than for points and lines; see "Antialiasing,"
for details.
<H4>
Polygons as Points, Outlines, or Solids</H4>
A polygon has two sides - front and back - and might be rendered differently
depending on which side is facing the viewer. This allows you to have cutaway
views of solid objects in which there is an obvious distinction between
the parts that are inside and those that are outside. By default, both
front and back faces are drawn in the same way. To change this, or to draw
only outlines or vertices, use <B>glPolygonMode()</B>. void <B>glPolygonMode</B>(GLenum
<B>face</B>,
GLenum <B>mode</B>);
<P>Controls the drawing mode for a polygon's front and back faces. The
parameter <I>face</I> can be GL_FRONT_AND_BACK, GL_FRONT, or GL_BACK; <I>mode</I>
can be GL_POINT, GL_LINE, or GL_FILL to indicate whether the polygon should
be drawn as points, outlined, or filled. By default, both the front and
back faces are drawn filled.
<P>For example, you can have the front faces filled and the back faces
outlined with two calls to this routine:
<PRE>glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_LINE);</PRE>
See the next section for more information about how to control which faces
are considered front-facing and which back-facing.
<H4>
Reversing and Culling Polygon Faces</H4>
By convention, polygons whose vertices appear in counterclockwise order
on the screen are called front-facing. You can construct the surface of
any "reasonable" solid - a mathematician would call such a surface an orientable
manifold (spheres, donuts, and teapots are orientable; Klein bottles and
M鯾ius strips aren't) - from polygons of consistent orientation. In other
words, you can use all clockwise polygons, or all counterclockwise polygons.
(This is essentially the mathematical definition of <I>orientable</I>.)
<P>Suppose you've consistently described a model of an orientable surface
but that you happen to have the clockwise orientation on the outside. You
can swap what OpenGL considers the back face by using the function <B>glFrontFace()</B>,
supplying the desired orientation for front-facing polygons.void <B>glFrontFace</B>(GLenum
<I>mode</I>);
<P>Controls how front-facing polygons are determined. By default, <I>mode</I>
is GL_CCW, which corresponds to a counterclockwise orientation of the ordered
vertices of a projected polygon in window coordinates. If <I>mode</I> is
GL_CW, faces with a clockwise orientation are considered front-facing.
<P><B>Advanced</B>
<P>In more technical terms, the decision of whether a face of a polygon
is front- or back-facing depends on the sign of the polygon's area computed
in window coordinates. One way to compute this area is
<P><IMG SRC="figures/eq201.gif" ALT="[IMAGE]" NOSAVE HEIGHT=70 WIDTH=225>
<P>where <I>x</I>i and <I>y</I>i are the <I>x</I> and <I>y</I> window coordinates
of the <I>i</I>th vertex of the <I>n</I>-vertex polygon and:
<P><IMG SRC="figures/eq202.gif" ALT="[IMAGE]" NOSAVE HEIGHT=29 WIDTH=156>
<P>Assuming that GL_CCW has been specified, if <I>a</I>>0, the polygon
corresponding to that vertex is considered to be front-facing; otherwise,
it's back-facing. If GL_CW is specified and if <I>a</I><0, then the
corresponding polygon is front-facing; otherwise, it's back-facing.
<P>In a completely enclosed surface constructed from polygons with a consistent
orientation, none of the back-facing polygons are ever visible - they're
always obscured by the front-facing polygons. In this situation, you can
maximize drawing speed by having OpenGL discard polygons as soon as it
determines that they're back-facing. Similarly, if you are inside the object,
only back-facing polygons are visible. To instruct OpenGL to discard front-
or back-facing polygons, use the command <B>glCullFace()</B> and enable
culling with <B>glEnable()</B>. void <B>glCullFace</B>(GLenum <I>mode</I>);
<P>Indicates which polygons should be discarded (culled) before they're
converted to screen coordinates. The mode is either GL_FRONT, GL_BACK,
or GL_FRONT_AND_BACK to indicate front-facing, back-facing, or all polygons.
To take effect, culling must be enabled using <B>glEnable()</B> with GL_CULL_FACE;
it can be disabled with <B>glDisable()</B> and the same argument.
<H4>
Stippling Polygons</H4>
By default, filled polygons are drawn with a solid pattern. They can also
be filled with a 32-bit by 32-bit window-aligned stipple pattern, which
you specify with <B>glPolygonStipple()</B>. void <B>glPolygonStipple</B>(const
GLubyte *<I>mask</I>);
<P>Defines the current stipple pattern for filled polygons. The argument
<I>mask</I>
is a pointer to a 32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -