O'Reilly Network    
 Published on O'Reilly Network (http://www.oreillynet.com/)
 See this if you're having trouble printing code examples

Creating Real Time 3D Graphics With OpenGL

by Chris Halsall

You see a missile coming at you, fired by an opponent off on another platform. Its translucent smoke trail is more of a give-away than the rocket flame, which is mostly obscured by the missile as it hurls itself directly towards you. Dart to the right, off the ledge, while you rail-gun your opponent; his body comes apart into pieces, each bouncing around leaving bloody stains where they hit.

While not everyone may agree with the content of Quake3 Arena, or any of a multitude of other violent games available, it's hard not to be impressed with the technical sophistication of the images produced. Many, including Q3A, rely on the OpenGL Application Programming Interface (API) to do the actual rendering. OpenGL is a good choice for developers who want to produce real-time 3D images because it's cross platform and mature. OpenGL (or a clone) API is available on most modern desktops, with some taking advantage of 3D hardware acceleration provided by the video card.

A brief OpenGL history

Images from Q3A rely on the OpenGL API for rendering.

Figure 1. Images from Quake3 Arena rely on the OpenGL API for their rendering.

OpenGL was developed by SGI (split off from IrixGL when the company was still known as Silicon Graphics), and the OpenGL name is a registered trademark owned by the company. For many years, the only real access to OpenGL was by way of high-end Unix workstations, which were used for engineering, scientific, and visualization work. SGI's IRIX-based machines were generally considered to be the best, as they usually came with leading-edge, highly optimized 3D acceleration hardware. They also came with extremely high price tags.

For anyone who wanted to provide the OpenGL API itself (as opposed to just using the API as a client program), SGI licensed the use of the name, a set of conformance tests, and a Sample Implementation (SI) in software for $100,000, with binary redistribution rights available for an additional $5 per copy royalty. Having this license and passing the tests gave someone the right to claim to be truly OpenGL compliant.

Fast-forward a few years and bring mass-market consumer economics to bear, and 3D acceleration hardware which used to cost $50,000 is now available for $250. Oh, and it's faster. It seems people just can't get enough of shooting at each other, and those who have machines that can render high-resolution displays at high frame rates have a better chance of taking out their opponents.

Related Articles:

OpenGL Rendering and Drawing

Preparing to Build an OpenGL Application

Utah GLX

In order to still be considered open, and to help get their API used, SGI has always allowed the copying of the OpenGL header files in order to produce compatible "clones." Examples include all the various "MiniGL" versions available for different 3D hardware cards under Windows. These are often written solely with games in mind and may not work well with, for example, a CAD program.

Just recently, SGI has revised the access terms to their SI to be much more "open." Available for free download, the new license now allows hardware vendors who based their drivers on the SI to release their code in source form, if they so choose. This is great news for users and developers on Linux, and continues SGI's commitment to contributing technologies to the open source community. It's important to note, however, that SGI still owns, controls, and limits the use of the term OpenGL.

One clone implementation of particular interest to Linux/Free Unix users is the Mesa 3-D graphics library, written by Brian Paul and others at www.mesa3d.org. Mesa is a GPLed, OpenGL-like implementation which until recently was as close to "real" OpenGL as you can get (with source code) without paying money. And while SGI's SI does provide "complete feature coverage," including new imaging features defined in OpenGL 1.2, Mesa actually turns out to be a bit faster in some situations. SGI is quite supportive of Mesa, and has recently given Brian a copy of the conformance tests to use. Mesa is still not allowed to claim to be OpenGL, however.

What exactly is OpenGL?

OpenGL is an API to assist in delivering 3D drawing services in real-time environments. It's an immediate mode design, in that each frame is drawn explicitly by the client application, and each mode change will affect all subsequent drawing calls. This is instead of a retained mode design (like SGI's IRIX Performer), where the client application first describes the scene and then changes the camera and objects as needed.

The OpenGL API itself is controlled by an independent board, known as the Architecture Review Board (ARB), with each member having a single vote. The ARB governs changes and extensions to the API, new releases, and the conformance tests. This ensures that SGI can't solely control where the standard goes. News and development information is available at the OpenGL.org site.

It's interesting to note that through its extension functions, new abilities are added to OpenGL in a very open-source manner. Any implementer can add a new extension, so long as it includes a prefix which identifies it as unique to the implementer. If the extension is submitted to the ARB and approved for adoption, it then becomes part of the official standard.

Figure 2. The classic teapot example to help developers with shape design.

The classic teapot object to help developers with lighting and texture design

The API is carefully designed to allow large portions of the work to be carried out with the assistance of 3D hardware. A full implementation (like OpenGL or Mesa, but unlike many of the MiniGLs) will fall back from hardware acceleration to a software version for any features requested that aren't available from the hardware. This is referred to as falling back from the fast path to a slow path and can dramatically lower the frame rate delivered.

Rendering, or drawing, complex and realistic scenes full-screen at 50 frames per second is not possible even with today's fastest general-purpose processors, so specialized hardware assistance is needed for most applications. Small demonstration programs can still be run solely with software rendering, for example, as can applications where high frame rates aren't needed. But once hardware acceleration is used, no one is ever willing to go back.

To the application program author, OpenGL provides approximately 250 calls, or entry points, that are used to set up the rendering environment, create lights, and set background colors, drawing and blending modes, etc. Calls are also provided for drawing points, lines, polygons (convex and planar only, please), and bitmaps. These can be painted with textures and "lit" in different ways.

OpenGL provides several different types of buffers that the programmer can use to render the scene. For example, the frame or color buffer is where the actual drawing that is seen by the user takes place. There may be several frame buffers available, including front and back versions of both left and right buffers. Each OpenGL implementation can offer all of these, plus additional auxiliary buffers, or may only provide a subset. At the minimum, at least one frame buffer must be available.

Other buffer types include a depth or Z buffer, which is used to eliminate hidden surfaces, and a stencil buffer, used to control where drawing takes place. Lastly, an accumulation buffer can be used to blend scenes together for motion blur and anti-aliasing effects. Not all buffers are supported in hardware on all devices though, and using an unsupported buffer will slow the refresh rate down considerably.

There are also several support libraries available for use with OpenGL, two of the most important being the OpenGL Utility (GLU) library and the OpenGL Utility Toolkit (GLUT). The former provides functions that help in creating texture mipmaps (explained below), accessing extended functions of OpenGL, as well as several that assist in building different object types including complex, curved NURBs and quadratic surfaces.

The latter library, GLUT, was written by Mark Kilgard, and is a windowing-system-independent toolkit designed to let a program run anywhere, regardless of the platform. In addition to window creation, handling, and event-processing functions, the library also provides several object creation functions. Included are wire and solid versions of a sphere, cube, torus, and cone, plus icosa-, octa-, tetra- and dodeca-hedrons. And, just for fun, a teapot is available at the request of a single function call.

3D programming is quite math intensive, relying on passing objects through 4x4 floating point transform matrices in order to figure out how a bunch of rotated, transformed, scaled objects map to a rotated, transformed, scaled projection. While those strong in math are welcome to manipulate the various matrices directly, those to whom math is rather intimidating can still produce impressive results using OpenGL and nothing but the simplest trigonometry.

Texture mapping

Several years ago some high-IQ types realized that if you could wrap two-dimensional images around three-dimensional objects, you could make them look much more realistic. Rather than trying to represent all the detail of a scene with individual geometry, it also turns out to be much faster to texture map fine details onto a surface than add many more triangles.

Texture maps are so important that many consumer-level 3D-accelerated cards now include two independent texture rendering units in silicon. This means two different texture maps can be applied to an object in one pass. So, for example, one texture might be the usual surface texture of a brick wall, and the other texture might be a light-map from a nearby lightbulb.

Texture mapping is extremely computationally intensive, and it becomes even more so as additional filtering is turned on. The filtering is desired in order to make the textures look reasonable when they're displayed at sharp angles or at a partial magnification. The use of mipmaps can also aid in making textures look better when they are viewed from far away. Mipmaps don't take more CPU time (except at creation), but they do require more memory.

Figure 3. Texture mapping is computationally intensive.

Figure 3. Texture mapping is computationally intensive.

Textures can be applied to an object in a variety of ways for different effects and can include an alpha or transparency channel. Depending on the mode chosen, a texture can be applied as a decal to an object, it can simply replace the object's color, or it can be blended or modulated with the object's existing color. Using textures with an alpha channel, it's possible to "punch holes" in an object or make the edge of an object appear irregular.

Texture mapping is an art form, with the need for creative tricks with patterns and an artist's hand to create the textures themselves. Any graphics program can be used to create RGB (color) textures, and advanced programs like Photoshop and the Gimp can be used to create RGBA (color with alpha channel) textures. Textures can also be created dynamically by way of the creative use of code.

It's important to note that most OpenGL applications are limited in the size of the textures that are allowed, some as small as 256 pixels square. Textures' sizes must also be a power-of-2, although the width and height need not be the same. For example, a texture sized 128 by 4 pixels is valid, while one 60 by 30 is not.

OpenGL solutions for Linux

As mentioned above, both the OpenGL SI from SGI and the GPLed Mesa are available for Linux. Mesa is often included with Linux distributions, at least in the form of client libraries. Versions intended for developers, with the required header files, aren't always included, however, and might need to be downloaded and installed. A quick search on FreshMeat.net for OpenGL will also find many available miniGLs targeted at game developers.

Later versions of MesaGL are also able to leverage on installed 3dfx Voodoo2/3, Matrox G200/400, ATI Rage Pro, or Intel i810 video cards to provide hardware acceleration, to some degree or another. However, because of technical limitations in XFree86 3.x, accelerated 3D-in-a-window is almost impossible to do, and Mesa can only provide acceleration for full-screen mode.

Thanks to SGI's contribution to the open source community of GLX, a special high-speed, direct-to-hardware-within-X rendering infrastructure they developed for their own IRIX environment, the full-screen-only problem under XFree86 has been solved. First SGI, then RedHat, then several other video card vendors paid Precision Insight to port GLX and Mesa to work with XFree86 4.0 and a variety of accelerated 3D cards in a fully integrated solution called the Direct Rendering Infrastructure (DRI). The DRI allows windows to be rendering using available hardware and can even handle accelerating more than one window at a time.

Although it will take a few months for XFree86 4.0 to become available as an off-the-CD install option for common Linux distributions, when it does there will be cheering from a great many 3D video card owners. For those who can't wait, the complete DRI codebase (including XFree 86 4.0) is available from CVS on sourceforge.net. Details are available at (URL:dri.sourceforge.net/), but be warned: This is not for end-users yet.

For those who need 3D acceleration-in-a-window today, and don't want to deal with ".0" code, a few commercial solutions do exist. For example, Xi Graphics offers their 3D Accelerated-X product, with several drivers available for specific cards. For most people, though, simply waiting until XFree86 4.0 becomes available will be the easiest and cheapest route.

OpenGL: the cross-platform choice

Figure 4. With OpenGL you can throw together some code which results in clients' and friends' mouths dropping open.

Figure 4. With OpenGL you can throw together some code which results in clients' and friends' mouths dropping open.

OpenGL is the only truly cross-platform 3D API available that is designed for hardware acceleration. Write an application using OpenGL to run on one system, and it should port to another platform with little more than running a build in the new environment. Linux to IRIX to Windows; there's even a MiniGL for the Palm.

OpenGL's ability to port to Windows is probably what prompted Microsoft to develop Direct3D, a competing API that many Windows game developers are using. Direct3D is now up to version 7, and it's beginning to look promising. The problem is, of course, that it's limited to a single platform.

OpenGL continues to be the only choice for most high-end, real-time applications, particularly in the simulation, scientific, and technical fields. Many 3D environment systems are also built on top of OpenGL to do the actual rendering. For example, SGI's IRIX Performer and id Software's Quake SDK both use OpenGL, but abstract the developer from much of the low-level detail.

Of course, the low-level details are exactly what some developers are after, and getting down and dirty may be the only way to achieve some desired effect or another. Knowing the right tool for a particular problem is of course a large part of a programmer's skill-set.

Having a working knowledge of OpenGL can be a very empowering ability. You can quickly throw together a bit of code which results in clients', friends', and coworkers' mouths dropping open. It can also help to understand what an application that uses OpenGL is actually doing to produce its images.

And, last but not least, programming 3D applications is simply fun! With ever more powerful hardware coming into the hands of more and more users, and SGI actively encouraging OpenGL's deployment on Linux, the possibilities are only going to become more exciting over time.

Chris Halsall is the Managing Director of Ideas 4 Lease (Barbados). Chris is a specialist... at automating information gathering and presentation systems.

Discuss this article in the O'Reilly Network Forum.

Return to the O'Reilly Network Hub.

Copyright © 2009 O'Reilly Media, Inc.