1.5. A Simple ExampleThe OpenGL code shown in Listing 1-1, although very simple, should serve as a good introduction. This program, called SimpleExample, is available from the book's Web site. It draws a white triangle on a black background, as shown in Figure 1-3. Listing 1-1. SimpleExample program
Figure 1-3. Output from the SimpleExample program.The first three header files<GL/glut.h>, <GL/glu.h>, and <GL/gl.h> contain definitions for GLUT, GLU, and OpenGL, respectively. They're followed by some standard C/C++ header files. This code uses the C preprocessor to define a value that identifies the Quit menu option. When the user opens the menu and selects the Quit option, GLUT passes this identifier to the menu callback function. Modern programming style avoids use of global variables, but they are still useful and acceptable for small demos such as this. In this case, the code defines an OpenGL display list identifier as a global. The application initializes it in the init() function and references it in the display() callback. OpenGL display lists can store many types of OpenGL commands, but this list holds only drawing commands. For more information on display lists, see Chapter 2, "Drawing Primitives." GLUT calls the display() callback function when necessary to refresh the window. In this example, this function includes OpenGL calls to clear the window, load a transformation matrix, call the display list that contains the commands to draw the triangle, and check for errors. It also contains a GLUT call to swap buffers. The next function, reshape(), also a GLUT callback, is executed when the user resizes the window. The function issues OpenGL commands to draw to the full window and maintain the correct aspect ratio and projection. It, too, checks for errors. GLUT calls the mainMenuCB() function when the user selects an item from the pop-up menu. This function checks only to see whether the item selected is the Quit item, and if so, it causes the application to exit. The init() function configures OpenGL and creates the display list. There are many ways to draw primitives in OpenGL. To keep this example simple, it demonstrates only two methods: the glBegin()/glEnd() method and vertex arrays. Because the vertex arrays feature isn't available in OpenGL version 1.0, the code queries OpenGL for its version. If the version is 1.1 or later, the code uses a vertex array rendering command to draw the triangle; otherwise, it uses glBegin()/glEnd(). It's common for OpenGL applications to choose which features to use based on the OpenGL version. Regardless of the method, the application stores the drawing commands in a display list. Note that display lists store only OpenGL commands. The conditional to check the version gets executed only when the display list is constructed, to determine its contents. When the display() function executes (or calls) the list, only the stored OpenGL commands are executedeither the vertex array call or the glBegin()/glEnd() calls, but not the conditional. Display lists are an effective way to both reduce the number of function calls, as well as eliminate conditionals that are constant at runtime. Finally, the init() function registers the callback functions and creates the GLUT pop-up menu. The main() routine performs GLUT initialization to create a window and rendering context. After creating the window, main() calls init() to perform further initialization. Finally, it calls glutMainLoop(), which waits for events and messages, and calls back to the application when necessary. |