Describing Points, Lines, and Polygons (State Management and Drawing Geometric Objects) (OpenGL Programming) Part 2

Restrictions on Using glBegin() and glEnd()

The most important information about vertices is their coordinates, which are specified by the glVertex*() command. You can also supply additional vertex-specific data for each vertex—a color, a normal vector, texture coordinates, or any combination of these—using special commands. In addition, a few other commands are valid between a glBegin() and glEnd() pair. Table 2-3 contains a complete list of such valid commands.

Command

Purpose of Command

glVertex*()

set vertex coordinates

glColor*()

set RGBA color

gllndex*()

set color index

glSecondaryColor*()

set secondary color for post-texturing application

glNormal*()

set normal vector coordinates

glMaterial*()

set material properties

glFogCoord*()

set fog coordinates

Table 2-3 Valid Commands Between glBegin() and glEnd()

Command


Purpose of Command

glTexCoord*()

set texture coordinates

glMultiTexCoord*()

set texture coordinates for multitexturing

glEdgeFlag*()

control drawing of edges

gl Array Element()

extract vertex array data

glEvalCoord*(), glEvalPoint*()

generate coordinates

glCallList(), glCallListsQ

execute display list(s)

Table 2-3 Valid Commands Between glBeginQ and glEnd()

No other OpenGL commands are valid between a glBegin() and glEnd() pair, and making most other OpenGL calls generates an error. Some vertex array commands, such as glEnableClientState() and glVertexPointer(), when called between glBegin() and glEnd(), have undefined behavior but do not necessarily generate an error. (Also, routines related to OpenGL, such as glX*() routines, have undefined behavior between glBegin() and glEnd().) These cases should be avoided, and debugging them may be more difficult.

Note, however, that only OpenGL commands are restricted; you can certainly include other programming-language constructs (except for calls, such as the aforementioned glX*() routines). For instance, Example 2-4 draws an outlined circle.

Example 2-4 Other Constructs Between glBeginf) and glEndQ

Other Constructs Between glBeginf) and glEndQ

Note: This example isn’t the most efficient way to draw a circle, especially if you intend to do it repeatedly. The graphics commands used are typically very fast, but this code calculates an angle and calls the sin() and cos() routines for each vertex; in addition, there’s the loop overhead.If you need to draw numerous circles, calculate the coordinates of the vertices once and save them in an array and create a display list,or use vertex arrays to render them.

Unless they are being compiled into a display list, all glVertex*() commands should appear between a glBegin() and glEnd() combination. (If they appear elsewhere, they don’t accomplish anything.) If they appear in a display list, they are executed only if they appear between a glBegin() and a glEnd().

Although many commands are allowed between glBegin() and glEnd(), vertices are generated only when a glVertex*() command is issued. At the moment glVertex*() is called, OpenGL assigns the resulting vertex the current color, texture coordinates, normal vector information, and so on. To see this, look at the following code sequence. The first point is drawn in red, and the second and third ones in blue, despite the extra color commands:

tmp5324-66

You can use any combination of the 24 versions of the glVertex*() command between glBegin() and glEnd(), although in real applications all the calls in any particular instance tend to be of the same form. If your vertex-data specification is consistent and repetitive (for example, glColor*, glVertex*, glColor*, glVertex*,…), you may enhance your program’s performance by using vertex arrays. (See "Vertex Arrays" on page 65.)

Next post:

Previous post: