OpenGL-Related Libraries

OpenGL provides a powerful but primitive set of rendering commands, and all higher-level drawing must be done in terms of these commands. Also, OpenGL programs have to use the underlying mechanisms of the windowing system. Several libraries enable you to simplify your programming tasks, including the following:

•  The OpenGL Utility Library (GLU) contains several routines that use lower-level OpenGL commands to perform such tasks as setting up matrices for specific viewing orientations and projections, performing polygon tessellation, and rendering surfaces. This library is provided as part of every OpenGL implementation. Portions of the GLU are described in the OpenGL Reference Manual.

• For every window system, there is a library that extends the functionality of that window system to support OpenGL rendering. For machines that use the X Window System, the OpenGL Extension to the X Window System (GLX) is provided as an adjunct to OpenGL. GLX routines use the prefix glX. For Microsoft Windows, the WGL routines provide the Windows to OpenGL interface. All WGL routines use the prefix wgl. For IBM OS/2, the PGL is the Presentation Manager to OpenGL interface, and its routines use the prefix pgl. For Apple, the AGL is the interface for systems that support OpenGL, and AGL routines use the prefix agl.

In addition, the GLX routines are also described in the OpenGL Reference Manual.


• The OpenGL Utility Toolkit (GLUT) is a window-system-independent toolkit, written by Mark Kilgard, to hide the complexities of differing window system APIs.GLUT routines use the prefix glut. To obtain the source code to GLUT, see "How to Obtain the Sample Code" on page xxiv of this topic.

Include Files

For all OpenGL applications, you want to include the gl.h header file in every file. Almost all OpenGL applications use GLU, the aforementioned OpenGL Utility Library, which requires inclusion of the glu.h header file. So almost every OpenGL source file begins with

tmp5324-6_thumb

Note: Microsoft Windows requires that windows.h be included before either gl.h or glu.h, because some macros used internally in the Microsoft Windows version of gl.h and glu.h are defined in windows.h.

The OpenGL library changes all the time. The various vendors that make graphics hardware add new features that may be too new to have been incorporated in gl.h. In order for you to take advantage of these new extensions to OpenGL, an additional header file is available, named glext.h. This header contains all of the latest extensions and can usually be found at the Web site of the company that manufactured your graphics hardware, or at the OpenGL Web Site (http: / /www. opengi. org/). As with any header, you could include it with the following statement:

tmp5324-7_thumb

You probably noticed the quotes around the filename, as compared to the normal angle brackets. Because glext.h is how graphics card vendors enable access to new extensions, you will probably need to download versions frequently from the Internet, so having a local copy to compile your program is not a bad idea. Additionally, you may not have permission to place the glext.h header file in a system header-file include directory (such as /usr/inciude on Unix-type systems).

If you are directly accessing a window interface library to support OpenGL, such as GLX, AGL, PGL, or WGL, you must include additional header files.

For example, if you are calling GLX, you may need to add these lines to your code:

tmp5324-8_thumb

In Microsoft Windows, the WGL routines are made accessible with

tmp5324-9_thumb

If you are using GLUT for managing your window manager tasks, you should include

tmp5324-10_thumb

Note: glut.h guarantees that gl.h and glu.h are properly included for you, so including all three files is redundant. Additionally, glut.h makes sure that any internal operating system dependent macros are properly defined before including gl.h and glu.h. To make your GLUT programs portable, include glut.h and do not explicitly include either gl.h or glu.h.

Most OpenGL applications also use standard C library system calls, so it is common to include header files that are not related to graphics, such as

tmp5324-11_thumb

We don’t include the header file declarations for our examples in this text, so our examples are less cluttered.

GLUT, the OpenGL Utility Toolkit

As you know, OpenGL contains rendering commands but is designed to be independent of any window system or operating system. Consequently, it contains no commands for opening windows or reading events from the keyboard or mouse. Unfortunately, it’s impossible to write a complete graphics program without at least opening a window, and most interesting programs require a bit of user input or other services from the operating system or window system. In many cases, complete programs make the most interesting examples, so this topic uses GLUT to simplify opening windows, detecting input, and so on. If you have implementations of OpenGL and GLUT on your system, the examples in this topic should run without change when linked with your OpenGL and GLUT libraries.

In addition, since OpenGL drawing commands are limited to those that generate simple geometric primitives (points, lines, and polygons), GLUT includes several routines that create more complicated three-dimensional objects, such as a sphere, a torus, and a teapot. This way, snapshots of program output can be interesting to look at. (Note that the OpenGL Utility Library, GLU, also has quadrics routines that create some of the same threedimensional objects as GLUT, such as a sphere, cylinder, or cone.)

GLUT may not be satisfactory for full-featured OpenGL applications, but you may find it a useful starting point for learning OpenGL. The rest of this section briefly describes a small subset of GLUT routines so that you can follow the programming examples in the rest of this topic.

Window Management

Five routines perform tasks necessary for initializing a window:

•    glutlnit(int *argc, char **argv) initializes GLUT and processes any command line arguments (for X, this would be options such as -display and -geometry). glutlnit() should be called before any other GLUT routine.

•    glutInitDisplayMode(unsigned int mode) specifies whether to use an RGBA or color-index color model. You can also specify whether you want a single- or double-buffered window. (If you’re working in color-index mode, you’ll want to load certain colors into the color map; use glutSetColor() to do this.) Finally, you can use this routine to indicate that you want the window to have an associated depth, stencil, multisampling, and/or accumulation buffer. For example, if you want a window with double buffering, the RGBA color model, and a depth buffer, you might call glutInitDisplayMode(GL[/T_DOl/BL£ | GLUT_RGB | GL UT_DEPTH).

•    glutInitWindowPosition(int x, int y) specifies the screen location for the upper-left corner of your window.

•    glutlnitWindowSizefint width, int size) specifies the size, in pixels, of your window.

•    int glutCreateWindow(char *string) creates a window with an OpenGL context. It returns a unique identifier for the new window. Be warned: until glutMainLoopO is called, the window is not yet displayed.

The Display Callback

glutDisplayFunc(void {*fnnc)(void)) is the first and most important event callback function you will see. Whenever GLUT determines that the contents of the window need to be redisplayed, the callback function registered by glutDisplayFunc() is executed. Therefore, you should put all the routines you need to redraw the scene in the display callback function.

If your program changes the contents of the window, sometimes you will have to call glutPostRedisplay(), which gives glutMainLoopO a nudge to call the registered display callback at its next opportunity.

Running the Program

The very last thing you must do is call glutMainLoopO. All windows that have been created are now shown, and rendering to those windows is now effective. Event processing begins, and the registered display callback is triggered. Once this loop is entered, it is never exited!

Example 1-2 shows how you might use GLUT to create the simple program shown in Example 1-1. Note the restructuring of the code. To maximize efficiency, operations that need to be called only once (setting the background color and coordinate system) are now in a procedure called init(). Operations to render (and possibly re-render) the scene are in the displav() procedure, which is the registered GLLTT display callback.

Example 1-2 Simple OpenGL Program Using GLUT: hello.c

Simple OpenGL Program Using GLUT: hello.c

 

 

 

Simple OpenGL Program Using GLUT: hello.c

Handling Input Events

You can use the following routines to register callback commands that are invoked when specified events occur:

•    glutReshapeFunc(void (*func)(int w, int h)) indicates what action should be taken when the window is resized.

•    glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)) and glutMouseFunc(void (*func)(int button, int state, int x, int y)) allow you to link a keyboard key or a mouse button with a routine that’s invoked when the key or mouse button is pressed or released.

•    glutMotionFunc(void (*func)(int x, int y)) registers a routine to call back when the mouse is moved while a mouse button is also pressed.

Managing a Background Process

You can specify a function that’s to be executed if no other events are pending—for example, when the event loop would otherwise be idle—with glutIdleFunc(void (*func)(void)). This routine takes a pointer to the function as its only argument. Pass in NULL (zero) to disable the execution of the function.

Drawing Three-Dimensional Objects

GLUT includes several routines for drawing these three-dimensional objects:

cone

icosahedron

teapot

cube

octahedron

tetrahedron

dodecahedron

sphere

torus

You can draw these objects as wireframes or as solid shaded objects with surface normals defined. For example, the routines for a cube and a sphere are as follows:

void glutWireCube(GLdouble size);

void glutSolidCube(GLdouble size);

void glutWireSphere(GLdouble radius, GLint slices, GLint stacks);

void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);

All these models are drawn centered at the origin of the world coordinate system.

Next post:

Previous post: