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
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:
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.)