CS 428 - OpenGL review

Online resources

Official OpenGL website
OpenGL Programming Guide (the red book)

OpenGL manual pages (local)
            GL       GLU


Brief description

OpenGL is a graphics library initially developed at SGI, which is now developed through an industry consortium. It is commonly used in both the high-end and low-end 3D markets, and can also be used in the development of 2D applications.

The OpenGL interface is basically a state machine that has facilities to specify graphical objects (points, lines, polygons, ...) and their attributes, and to manipulate images. This document provides a brief review of the elementary concepts in OpenGL. It is not meant as a substitute for the OpenGL Programming Guide. Note that several more advanced concepts are mentioned here, which won't be needed on the first assignment.

OpenGL conventions

Note: This page describes the C/C++ interface to OpenGL. The Java interface is described here. You should still be familiar with the C interface, as both the textbook and the OpenGL programming manual use C.

OpenGL library functions all begin with "gl", defined constants begin with "GL_", and types begin with "GL". Other related libraries (such as the OpenGL Utility library, GLU) have similar naming conventions (in GLU, all functions begin with "glu").

When using OpenGL, you will need to include:

#include <GL/gl.h>

and if you are using any functions from the GLU library:

#include <GL/glu.h>

Although if you are using GLUT (which is a cross-platform C++ library that provides access to OpenGL), then you won't need to explicitly specify these include files, as they are both included by the default GLUT include file.

The following is a table of types used in OpenGL. The C definitions of these types might not be the same across different platforms, or across different versions of OpenGL, so it's important to only use these types when writing OpenGL code, for communicating with the OpenGL API.

OpenGL typeC typeSuffix
GLbyte char b
GLubyte, GLboolean unsigned charub
GLshort short s
GLushort unsigned short   us
GLint,GLsizei int i
GLuint, GLenum, GLbitfield       unsigned intui
GLfloat,GLclampf float f
GLdouble,GLclampd double d
GLvoid void  

Since only a C interface is provided to OpenGL, no function or operator overloading is possible, as in C++. As a result, OpenGL operations are implemented with a family of functions. For example, the family of functions used to set the current drawing color all begin with "glColor" and end with a specification of the data used to specify the color. In general, this trailing specification is:

When specifying a color, different types can be used for the individual components. In addition, the number of components can vary (normal colors are 3 values, but transparent colors are 4 components as they include an "alpha" value).

A few examples of calls for specifying colors:

glColor3i(0, 0, 0); 3 integers
glColor4f(0.0, 0.5, 0.5, 0.7); 4 floats
GLdouble red = { 1.0, 0.0, 0.0 };
glColor3dv(arr);
an array (vector) of 3 doubles

See the glColor man page for more examples of function names.

OpenGL state

The OpenGL API maintains a large state. Objects are created with attributes taken from the current state (such as the current color), along with the current transformation. Among other things, the state also specifies which drawing and rendering operations take place.

Here are some commonly used functions that change the state, and modify graphical objects specified after the change:
Part of state Function (and man page)
current color glColor
current material glMaterial
current normal vector glNormal
current point size glPointSize
current line width glLineWidth
current matrix mode glMatrixMode
polygon shading method
(flat vs. Gouraud)
glShadeModel

Other state quantities are simply switches, which are turned on and off using the functions glEnable and glDisable. For example, the call:

     glEnable(GL_LIGHTING);

turns on the OpenGL illumination model, so that the color of the viewed objects is determined by the positions of lights, and the current material properties. When lighting is disabled, the color of objects is specified by the current color.

Commonly used arguments to these functions include (all are described in the glEnable man page):
GL_BLEND If enabled, "alpha" values are used to determine how objects blend with the existing image (exactly how is specified with a blend function, specified using glBlendFunc).
GL_DEPTH_TEST If true, z-buffer comparisons are applied (note that this is independent of whether the z-buffer is updated)
GL_LIGHTING If true, uses the OpenGL illumination model (lights, materials) instead of the current color to determine how to render objects.

Specifying geometry

Geometric objects are specified first with the object type, and then by listing the object points (and attributes). Each object (or group of objects in some cases) is specified using the following code fragment:

    glBegin(...);

    /* vertices and attributes are specified here */

    glEnd();

The argument to glBegin is one of a series of modes to determine whether points, lines or polygons are specified, as well as their configuration. They are listed in the man page, as well as pictorially in the OpenGL Reference Guide in the section on Geometric Primitives (page 42-47, 2nd ed).

An example of this:

    GLfloat p1[3], p2[3], p3[3], p4[3], p5[3];

    /* Set p1,p2,p3,p4,p5 to something.... */

    /* Draw a red polygon with vertices p1,p2,p3 */
    glBegin(GL_TRIANGLES);
    glColor3f(1.0, 0.0, 0.0);
    glVertex3fv(p1);
    glVertex3fv(p2);
    glVertex3fv(p3);
    glEnd();

    /* Draw 2 lines; the first p1,p5 and the second p3,p5 */
    glBegin(GL_LINES);
    glColor3f(1.0, 1.0, 1.0);
    glVertex3fv(p1);
    glVertex3fv(p5);

    glColor3f(0.0, 0.0, 1.0);
    glVertex3fv(p3);
    glColor3f(0.0, 1.0, 0.0);
    glVertex3fv(p5);
    glEnd();

    /* Draw a loop of lines connecting p1,p2,p3 and back to p1
     * This is basically a green border on the above polygon
     */
    glBegin(GL_LINE_LOOP);
    glColor3f(0.0, 1.0, 0.0);
    glVertex3fv(p1);
    glVertex3fv(p2);
    glVertex3fv(p3);
    glEnd();

Again, recall that the color of the primitives is taken from the current color when the vertex was specified. It is possible to have a polygon or line consist of different colors (a smooth transition between them is produced between vertices).

Transparent objects

The fourth component of a color is an opacity value (often called "alpha"; it is the A in RGBA). When OpenGL draws a pixel of a transparent object, it blends what it is being drawn, with what is already present in the image (the previously drawn objects). To specify a transparent color, use one of the 4 component glColor functions.

However, for this to take effect, you must enable blending mode using:

   glEnable(GL_BLEND);
Aside from this, you also need to specify the method used to combine the source pixel color (what you are drawing in) with the destination pixel color (what is present in the image already). The function glBlendFunc allows this to be specified. Ordinary transparency is:
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
This means that the source pixels are scaled by alpha, the existing pixels are scaled by (1-alpha), and they are added together. So if alpha is 1, then the object is completely opaque. An alpha of 0 means that the object is not drawn at all.

Matrix stacks and transformations

OpenGL maintains several matrix stacks. The top matrix on each stack is used in the transformations performed by OpenGL. In this course, we will be using the modeling/viewing stack (GL_MODELVIEW) and the camera projection stack (GL_PROJECTION). Which one of these to use is specified using the glMatrixMode function. Other matrix stack functions that are commonly used include:
glPushMatrix Adds a matrix to the current matrix stack (duplicating the previous matrix at the top of the stack)
glPopMatrix Discards the current (topmost) matrix on the current stack
glLoadIdentity Replaces the current matrix with the Identity matrix
Geometric transformations modify the current matrix. These functions include: glTranslate, glRotate and glScale.

Viewing transformations (orthographic and projective) modify the current matrix (typically the mode will be GL_PROJECTION in this case). These functions include: glOrtho, glFrustum, gluOrtho2D and gluPerspective.

Clipping planes

In OpenGL, you can define planes that are used to clip geometry (this are in addition to the planes used for clipping to the window's view volume). There are at least six clipping planes defined in all implementations of OpenGL; they are named using the identifiers: GL_CLIP_PLANE0, GL_CLIP_PLANE1, GL_CLIP_PLANE2, ...

Clipping planes are specified using the function glClipPlane, which takes two arguments. The first is one of the clipping plane identifiers. The second is an array of four GLdoubles which define the plane (using the equation Ax + By + Cz + D = 0). The array stores A, B, C and D (in order).

Recall that the vector n = (A,B,C) is the unit-length normal vector for this plane. The retained geometry is on the side of this plane in which the normal vector is pointing; where Ax + By + Cz + D > 0. Also, given any point on the plane p it is easy to show that D = -p . n.

To actually perform clipping, a particular clipping plane must be enabled using glEnable. It will continue to be active until a corresponding call to glDisable. All geometry specified when a clipping plane is enabled will be clipped.

When they are defined, clipping planes are transformed using the current viewing matrix. This means that the clipping planes are transformed just like all other geometry. Of course, if the current transformation is changed after you define a clipping plane, this will not affect the clipping plane (but will affect the newly specified geometry).

See p. 139-141 in Chapter 3 of the OpenGL Programming Guide for more details (search for "Additional Clipping Planes" here).

Odds and ends

OpenGL buffers the data and requests that you specify. To flush out this buffer (so that the requests are not held until the buffer is full), use the function glFlush. Not doing this may cause the specified geometry not to be drawn immediately.

If you do not follow the OpenGL protocol (by using commands not allowed inside a glBegin() and glEnd(), or by popping an empty matrix stack, for example), an error status is set. This can be queried using glGetError.


428 Home