OpenGL Functions
OpenGL Functions
It is a window system independent, operating system independent graphics rendering API which
is capable of rendering high-quality color images composed of geometric and image primitives.
OpenGL is a library for doing computer graphics. By using it, you can create interactive
applications which render high-quality color images composed of 3D geometric objects and
images.
As OpenGL is window and operating system independent. As such, the part of your application
which does rendering is platform independent. However, in order for OpenGL to be able to
render, it needs a window to draw into. Generally, this is controlled by the windowing system on
whatever platform youre working on. Summarizing the above discussion, we can say OpenGL
is a software API to graphics hardware.
Designed as a streamlined, hardware-independent interface to be implemented on many
different hardware platforms.
Procedural interface.
No windowing commands.
No high-level commands.
This important diagram represents the flow of graphical information, as it is processed from CPU
to the frame buffer. There are two pipelines of data flow. The upper pipeline is for geometric,
vertex-based primitives. The lower pipeline is for pixel-based, image primitives. Texturing
combines the two types of primitives together.
OpenGL as a Renderer
OpenGL is a library for rendering computer graphics. Generally, there are two operations that
you do with OpenGL:
draw something
change the state of how OpenGL draws
OpenGL has two types of things that it can render: geometric primitives and image primitives.
Geometric primitives are points, lines and polygons. Image primitives are bitmaps and graphics
images (i.e. the pixels that you might extract from a JPEG image after youve read it into your
program.) Additionally, OpenGL links image and geometric primitives together using texture
mapping, which is an advanced topic well discuss this afternoon. The other common operation
that you do with OpenGL is setting state. Setting state is the process of initializing the internal
data that OpenGL uses to render your primitives. It can be as simple as setting up the size of
points and color that you want a vertex to be, to initializing multiple bitmap levels for texture
mapping.
Design Philosophy
GLUT simplifies the implementation of programs using OpenGL rendering. The GLUT
application programming interface (API) requires very few routines to display a graphics scene
rendered using OpenGL. The GLUT API (like the OpenGL API) is stateful. Most initial GLUT
state is defined and the initial state is reasonable for simple programs. The GLUT routines also
take relatively few parameters. No pointers are returned. The only pointers passed into GLUT are
pointers to character strings (all strings passed to GLUT are copied, not referenced) and opaque
font handles. The GLUT API is (as much as reasonable) window system independent. For this
reason, GLUT does not return any native window system handles, pointers, or other data
structures. More subtle window system dependencies such as reliance on window system
dependent fonts are avoided by GLUT; instead, GLUT supplies its own (limited) set of fonts. For
programming ease, GLUT provides a simple menu sub-API. While the meaning support is
designed to be implemented as pop-up menus, GLUT gives window system leeway to support
the menu functionality in another manner (pull-down menus for example). Two of the most
important pieces of GLUT state are the current window and current menu. Most window and
menu routines affect the current window or menu respectively. Most callbacks implicitly set the
current window and menu to the appropriate window or menu responsible for the callback.
GLUT is designed so that a program with only a single window and/or menu will not need to
keep track of any window or menu identifiers. This greatly simplifies very simple GLUT
programs. GLUT is designed for simple to moderately complex programs focused on OpenGL
rendering. GLUT implements its own event loop. For this reason, mixing GLUT with other APIs
that demand their own event handling structure may be difficult. The advantage of a built-in
event dispatch loop is simplicity.
GLUT contains routines for rendering fonts and geometric objects, however GLUT makes no
claims on the OpenGL display list name space. For this reason, none of the GLUT rendering
routines use OpenGL display lists. It is up to the GLUT programmer to compile the output from
GLUT rendering routines into display lists if this is desired. GLUT routines are logically
organized into several sub-APIs according to their functionality.
The sub-APIs are:
Initialization.
Command line processing, window system initialization, and initial window creation
state are controlled by these routines.
Beginning Event Processing.
This routine enters GLUT's event processing loop. This routine never returns, and it
continuously calls GLUT callbacks as necessary.
Window Management.
These routines create and control windows.
Overlay Management.
These routines establish and manage overlays for windows.
Menu Management.
These routines create and control pop-up menus.
Callback Registration.
These routines register callbacks to be called by the GLUT event processing loop.
Color Index Colormap Management.
These routines allow the manipulation of color index colormaps for windows.
State Retrieval.
These routines allows programs to retrieve state from GLUT.
Font Rendering.
These routines allow rendering of stroke and bitmap fonts.
Geometric Shape Rendering.
These routines allow the rendering of 3D geometric objects including spheres, cones,
icosahedrons, and teapots.
Miscellaneous window management functions
OpenGL: Conventions
Heres the basic structure that well be using in our applications. This is generally what youd do
in your own OpenGL applications.
The steps are:
1) Choose the type of window that you need for your application and initialize it.
2) Initialize any OpenGL state that you dont need to change every frame of your program. This
might include things like the background color, light positions and texture maps.
3) Register the callback functions that youll need. Callbacks are routines you write that GLUT
calls when a certain sequence of events occurs, like the window needing to be refreshed, or the
user moving the mouse. The most important callback function is the one to render your scene,
which well discuss in a few slides.
4) Enter the main event processing loop. This is where your application receives events, and
schedules when callback functions are called.
GLUT window and screen coordinates are expressed in pixels. The upper left hand corner of the
screen or a window is (0,0). X coordinates increase in a rightward direction; Y coordinates
increase in a downward direction. Note: This is inconsistent with OpenGL's coordinate scheme
that generally considers the lower left hand coordinate of a window to be at (0,0) but is
consistent with most popular window systems. Integer identifiers in GLUT begin with one, not
zero. So window identifiers, menu identifiers, and menu item indexes are based from one, not
zero. The functions in OpenGL always start with a specific prefix which is "gl" and a capitalized
first character of each word in the name of function syntax, which indicates that this function
belongs to the OpenGL library. In GLUT's ANSI C binding, for most routines, basic types ( int,
char*) are used as parameters. In routines where the parameters are directly passed to OpenGL
routines, OpenGL types ( GLfloat) are used. The header files for GLUT should be included in
GLUT programs with the following include directive:
#include <GL/glut.h>
Because a very large window system software vendor (who will remain nameless) has an
apparent inability to appreciate that OpenGL's API is independent of their window system API,
portable ANSI C GLUT programs should not directly include <GL/gl.h> or <GL/glu.h>. Instead,
ANSI C GLUT programs should rely on <GL/glut.h> to include the necessary OpenGL and
GLU related header files. The ANSI C GLUT library archive is typically named libglut.a on
Unix systems. GLUT programs need to link with the system's OpenGL and GLUT libraries (and
any libraries these libraries potentially depend on). A set of window system dependent libraries
may also be necessary for linking GLUT programs. For example, programs using the X11 GLUT
implementation typically need to link with Xlib, the X extension library, possibly the X Input
extension library, the X miscellaneous utilities library, and the math library.
Examples on OpenGL function formats:
Functions have prefix gl and initial capital letters for each word glClearColor(), glEnable(),
glPushMatrix()
OpenGL data types: GLfloat, GLdouble, GLint, GLenum,
glutInit
glutInit is used to initialize the GLUT library.
Usage
void glutInit(int *argcp, char **argv);
argcp
A pointer to the program's unmodified argc variable from main. Upon return, the value pointed to
by argcp will be updated, because glutInit extracts any command line options intended for the
GLUT library.
argv
The program's unmodified argv variable from main. Like argcp, the data for argv will be updated
because glutInit extracts any command line options understood by the GLUT library.
Description
glutInit will initialize the GLUT library and negotiate a session with the window system. During
this process, glutInit may cause the termination of the GLUT program with an error message to
the user if GLUT cannot be properly initialized. Examples of this situation include the failure to
connect to the window system, the lack of window system support for OpenGL, and invalid
command line options. glutInit also processes command line options, but the specific options
parse are window
system dependent.
glutInitWindowPosition, glutInitWindowSize
glutInitWindowPosition and glutInitWindowSize set the initial window position and size
respectively.
Usage
void glutInitWindowSize(int width, int height);
void glutInitWindowPosition(int x, int y);
width
Width in pixels.
height
Height in pixels.
x
Window X location in pixels.
y
Window Y location in pixels.
Description
Windows created by glutCreateWindow will be requested to be created with the current initial
window position and size.
glutInitDisplayMode
glutInitDisplayMode sets the initial display mode.
Usage
void glutInitDisplayMode(unsigned int mode);
mode: Display mode, normally the bitwise OR-ing of GLUT display mode bit masks. See values
below:
GLUT_RGBA : Bit mask to select an RGBA mode window. This is the default if neither
GLUT_RGBA
nor GLUT_INDEX are specified.
GLUT_RGB : An alias for GLUT_RGBA.
GLUT_INDEX : Bit mask to select a color index mode window. This overrides GLUT_RGBA if
it is also
specified.
GLUT_SINGLE : Bit mask to select a single buffered window. This is the default if neither
GLUT_DOUBLE or GLUT_SINGLE are specified.
GLUT_DOUBLE: Bit mask to select a double buffered window. This overrides GLUT_SINGLE
if it is also specified.
GLUT_ACCUM: Bit mask to select a window with an accumulation buffer.
GLUT_ALPHA :Bit mask to select a window with an alpha component to the color buffer(s).
GLUT_DEPTH : Bit mask to select a window with a depth buffer.
GLUT_STENCIL : Bit mask to select a window with a stencil buffer.
GLUT_MULTISAMPLE: Bit mask to select a window with multisampling support. If
multisampling is not available, a non-multisampling window will automatically be chosen. Note:
both the OpenGL client-side and server-side implementations must support the
GLX_SAMPLE_SGIS extension for multisampling to be available.
GLUT_STEREO : Bit mask to select a stereo window.
GLUT_LUMINANCE : Bit mask to select a window with a ``luminance'' color model. This
model provides the functionality of OpenGL's RGBA color model, but the green and blue
components are not maintained in the frame buffer. Instead each pixel's red component is
converted to an index between zero and glutGet(GLUT_WINDOW_COLORMAP_SIZE)-1 and
looked up in a per-window color map to determine the color of pixels within the window. The
initial colormap of GLUT_LUMINANCE windows is initialized to be a linear gray ramp, but
can be modified with GLUT's colormap routines.
Description
The initial display mode is used when creating top-level windows, subwindows, and overlays to
determine the OpenGL display mode for the to-be-created window or overlay. Note that
GLUT_RGBA selects the RGBA color model, but it does not request any bits of alpha
(sometimes called an alpha buffer or destination alpha) be allocated. To request alpha, specify
GLUT_ALPHA. The same applies to GLUT_LUMINANCE.
glVertex
The main function (and probably the most used OpenGL function) is function named glVertex.
This function defines a point (or a vertex) in your 3D world and it can vary from receiving 2 up
to 4 coordinates.
glVertex2f(100.0f, 150.0f); defines a point at x = 100, y = 150, z = 0; this function takes only 2
parameters, z is always 0. glVertex2f can be used in special cases and won't be used a lot unless
you're working with pseudo-2D sprites or triangles and points that always have to be constrained
by the depth coordinate.
glVertex3f(100.0f, 150.0f, -25.0f); defines a point at x = 100, y = 150, z = -25.0f; this function
takes 3 parameters, defining a fully 3D point in your world.
glVertex4f(100.0f, 150.0f, -25.0f, 1.0f); this is the same as glVertex3f, the only difference is in
the last coordinate that specifies a scaling factor. The scaling factor is set to 1.0f by default. It
can be used to make your 3D points look thicker than one pixel.
Animation
One of the most exciting things you can do on a graphics computer is draw pictures that move.
Whether youre an engineer trying to see all sides of a mechanical part youre designing, a pilot
learning to fly an airplane using a simulation, or merely a computer-game aficionado, its clear
that animation is an important part of computer graphics. In a movie theater, motion is achieved
by taking a sequence of pictures and projecting them at 24 per second on the screen. Each frame
is moved into position behind the lens, the shutter is opened, and the frame is displayed. The
shutter is momentarily closed while the film is advanced to the next frame, then that frame is
displayed, and so on. Although youre watching 24 different frames each second, your brain
blends them all into a smooth animation. (The old Charlie Chaplin movies were shot at 16
frames per second and are noticeably jerky.)
In fact, most modern projectors display each picture twice at a rate of 48 per second to reduce
flickering. Computer-graphics screens typically refresh (redraw the picture) approximately 60 to
76 times per second, and some even run at about 120 refreshes per second. Clearly, 60 per
second is smoother than 30, and 120 is marginally better than 60. Refresh rates faster than 120,
however, are beyond the point of diminishing returns, since the human eye is only so good. The
key reason that motion picture projection works is that each frame is complete when it is
displayed. Suppose you try to do computer animation of your million frame movie with a
program like this:
open_window();
for (i = 0; i < 1000000; i++) {
clear_the_window();
draw_frame(i);
wait_until_a_24th_of_a_second_is_over();
}
If you add the time it takes for your system to clear the screen and to draw a typical frame, this
program gives more and more disturbing results depending on how close to 1/24 second it takes
to clear and draw. Suppose the drawing takes nearly a full 1/24 second. Items drawn first are
visible for the full 1/24 second and present a solid image on the screen; items drawn toward the
end are instantly cleared as the program starts on the next frame. They present at best a ghostlike
image, since for most of the 1/24 second your eye is viewing the cleared background instead of
the items that were unlucky enough to be drawn last. The problem is that this program doesnt
display completely drawn frames; instead, you watch the drawing as it happens. Most OpenGL
implementations provide double-buffering - hardware or software that supplies two complete
color buffers. One is displayed while the other is being drawn. When the drawing of a frame is
complete, the two buffers are swapped, so the one that was being viewed is now used for
drawing, and vice versa. This is like a movie projector with only two frames in a loop; while one
is being projected on the screen, an artist is desperately erasing and redrawing the frame thats
not visible. As long as the artist is quick enough, the viewer notices no difference between this
setup and one where all the frames are already drawn and the projector is simply displaying them
one after the other.
With double-buffering, every frame is shown only when the drawing is complete; the viewer
never sees a partially drawn frame. A modified version of the preceding program that does
display smoothly animated graphics might look like this:
open_window_in_double_buffer_mode();
for (i = 0; i < 1000000; i++) {
clear_the_window();
draw_frame(i);
swap_the_buffers();
}
device and turn on and off an idle function. In this example, the mouse buttons toggle the
spinning on and off.
Transformation
Geometric image transformation functions use mathematical transformations to crop, pad, scale,
rotate, transpose or otherwise alter an image array to produce a modified view of an image. A
transformation thus is the process of mapping points to other locations. Common transformations
are Translation, Scaling and Rotation.
When an image undergoes a geometric transformation, some or all of the pixels within the source
image are relocated from their original spatial coordinates to a new position in the output image.
When a relocated pixel does not map directly onto the center of a pixel location, but falls
somewhere in between the centers of pixel locations, the pixel's value is computed by sampling
the values of the neighboring pixels.
Basic 2D Transforms
Scaling
OpenGL Transformation
Object Coordinates
It is the local coordinate system of objects and is initial position and orientation of objects before
any transform is applied. In order to transform objects, use glRotatef(),
glTranslatef(), glScalef().
Eye Coordinates
It is yielded by multiplying GL_MODELVIEW matrix and object coordinates. Objects
are transformed from object space to eye space using GL_MODELVIEW matrix in OpenGL.
GL_MODELVIEW matrix is a combination of Model and View matrices ( Mview . Mmodel).
Model transform is to convert from object space to world space. And,
View transform is to convert from world space to eye space.
Note that there is no separate camera (view) matrix in OpenGL. Therefore, in order to simulate
transforming the camera or view, the scene (3D objects and lights) must be transformed with the
inverse of the view transformation. In other words, OpenGL defines that the camera is always
located at (0, 0, 0) and facing to -Z axis in the eye space coordinates, and cannot be transformed.
See more details of GL_MODELVIEW matrix in ModelView Matrix.
Normal vectors are also transformed from object coordinates to eye coordinates for lighting
calculation. Note that normals are transformed in different way as vertices do. It is mutiplying
the tranpose of the inverse of GL_MODELVIEW matrix by a normal vector.
Clip Coordinates
It is after applying eye coordinates into GL_PROJECTION matrix. Objects are clipped out
from the viewing volume (frustum). Frustum is used to determine how objects are projected onto
screen (perspective or orthogonal) and which objects or portions of objects are clipped out of the
final image.
GL_PROJECTION matrix in Projection Matrix.
OpenGL uses 4 x 4 matrix for transformations. Notice that 16 elements in the matrix are stored
as 1D array in column-major order. You need to transpose this matrix if you want to convert it to
the standard convention, row-major format.
OpenGL has 4 different types of matrices; GL_MODELVIEW, GL_PROJECTION,
GL_TEXTURE, and GL_COLOR. You can switch the current type by using glMatrixMode()
in your code. For example, in order to select GL_MODELVIEW matrix, use
glMatrixMode(GL_MODELVIEW).
The 3 matrix elements of the rightmost column (m12, m13, m14) are for the translation
transformation, glTranslatef(). The element m15 is the homogeneous coordinate. It is specially
used for projective transformation.
3 elements sets, (m0, m1, m2), (m4, m5, m6) and (m8, m9, m10) are for Euclidean and affine
transformation, such as rotation glRotatef() or scaling glScalef(). Note that these 3 sets are
actually representing 3 orthogonal axes;
(m0, m1, m2) : +X axis, left vector, (1, 0, 0) by default
(m4, m5, m6) : +Y axis, up vector, (0, 1, 0) by default
(m8, m9, m10) : +Z axis, forward vector, (0, 0, 1) by default
We can directly construct GL_MODELVIEW matrix from angles or lookat vector
without using OpenGL transform functions. Here are some useful codes to build
GL_MODELVIEW matrix:
Angles to Axes
Lookat to Axes
Note that OpenGL performs matrices multiplications in reverse order if multiple transforms are
applied to a vertex. For example, If a vertex is transformed by MA first, and transformed by MB
second, then OpenGL performs MB x MA first before multiplying the vertex. So, the last
transform comes first and the first transform occurs last in your code.
// Note that the object will be translated first then rotated
glRotatef(angle, 1, 0, 0); // rotate object angle degree around X-axis
glTranslatef(x, y, z); // move object to (x, y, z)
drawObject();
For orthographic projection, this ratio will be 1, so the left, right, bottom and top values of the far
plane will be same as on the near plane.
You may also use gluPerspective() and gluOrtho2D() functions with less number of parameters.
gluPerspective() requires only 4 parameters; vertical field of view (FOV), the aspect ratio of
width to height and the distances to near and far clipping planes. The equivalent conversion from
gluPerspective() to glFrustum() is described in the following code.
glLoadMatrix{fd}(m) :
replace the current matrix with the matrix m.
glLoadTransposeMatrix{fd}(m) :
replace the current matrix with the row-major ordered matrix m.
glMultMatrix{fd}(m) :
multiply the current matrix by the matrix m, and update the result to the current matrix.
glMultTransposeMatrix{fd}(m) :
multiply the current matrix by the row-major ordered matrix m, and update the result to the
current matrix.
glGetFloatv(GL_MODELVIEW_MATRIX, m) :
return 16 values of GL_MODELVIEW matrix to m.
Note once again, OpenGL performs multiple transformations in reverse order, therefore, viewing
transform comes first before modeling transform in your code. And, if you want to rotate then
translate an object, put glTranslatef() first then glRotatef().
...
// initialze ModelView matrix
glLoadIdentity();
// ModelView matrix is product of viewing matrix and modeling matrix
3D Shapes in Open GL
Introduction
All is perfectly fine if we want to draw standard 2D shapes in OpenGL, but the next step up is
3D shapes, and it is these shapes that will really make your application look impressive. The best
part about 3D shapes, is that they are made up of 2D shapes, just drawn in 3D space.
While OpenGL provides methods for easily rendering 2D shapes, it doesnt provide any methods
for shapes such as cubes, spheres, pyramids, etc. But all is not lost, you have two choices. The
first choice is to create the shapes yourself, work out the vertices, determine which vertices you
want to use to make faces, and hand code it all in. The next choice, not including 3D modeling
applications and model loaders, is to use GLUT for simple 3D shapes. GLUT comes with the
ability to render some extremely basic 3D shapes such as a cube, sphere (without texture
coordinates), cone, torus/donut and the all famous teapot.
GLUT also lets us render this in both their wireframe version, or their regular filled version.
GLUT also comes with several other shapes, but they are not all that common. Lets take a
look at the code required to render these more common shapes:
Cube
1. glutWireCube(double size);
2. glutSolidCube(double size);
This will create a cube with the same width, height and depth/length, each the length of the size
parameter specified. This cube in GLUT also comes with surface normals but not texture
coordinates.
Sphere
1. glutWireSphere(double radius, int slices, int stacks);
2. glutSolidSphere(double radius, int slices, int stacks);
The calls to create a sphere in GLUT require you to give a radius, which determines the size of
the sphere, and the number of stacks and slices. The stacks and slices determine the quality of the
sphere, and are the number of divisions in vertical and horizontal directions. The sphere does
come with surface normals, but does not come with texture coordinates.
Cone
1. glutWireCone(double radius, double height, int slices, int stacks);
2. glutSolidCone(double radius, double height, int slices, int stacks);
If you want to create a cone, you would use the above GLUT calls. These calls are almost
identical to that of the sphere code, we have a radius and the stacks and slices. But it also takes
another parameter which defines the height of the cone. Also note that the radius of the cone,
refers to the radius of the base of the cone. The cone will come with surface normals, but does
not come with texture coordinates.
Torus
1. glutWireTorus(double inner_radius, double outer_radius, int sides, i
nt rings);
2. glutSolidTorus(double inner_radius, double outer_radius, int sides,
int rings);
A torus looks exactly like a donut. It has an inner radius, which specifies the size of the hole in
the middle, an outer radius, which specifies the outer side of the torus from the centre (not the
inner radius onwards), the sides specifies the number of sides in each radial section and finally,
the rings specify how many radial divisions are used for the torus.
Teapot
1. glutWireTeapot(double size);
2. glutSolidTeapot(double size);
The all famous teapot was first created in 1975 by Martin Newell and is widely used for testing
in computer graphics because it is round, has saddle points, can project a shadow onto itself and
looks decent when it is untextured. All you have to do to create the teapot is specify the size for
the teapot. The teapot comes with surface normals and texture coordinates which means it is
perfect for testing bump mapping, environment mapping, and many other effects.