Appendix D. Getting Started with OpenGL

Table of Contents

Manual Usage

Now that you understand at least the beginnings of graphics programming, it would be useful to discuss how to get started using OpenGL in your own projects. This discussion will assume that you know how to set up a build project in your build system of choice.

The easiest way is to just use the Unofficial OpenGL SDK. It is a well-documented collection of tools for writing simple OpenGL applications. It has functions for compiling shaders, the mouse-based controls we have used, image loading tools, and various other utilities that are vital to making OpenGL applications. Details for how to use it are found on the SDK's website.

Manual Usage

If you choose not to use the SDK, then you will have to build a set of useful tools yourself.

In order to use OpenGL, you will need to do two things. You must create a window and attach an OpenGL context to it, and you must load the OpenGL functions for that context. There are a number of other tools you may want (vector math, model loading, image loading, etc), but these tools are ones you need if you aren't going to do them manually.

Window and OpenGL Creation

Windows, displayable surfaces in GUI operating environments, are very platform-specific. Most Linux distributions rely on X11 for the lowest-level of window creation, and X11 has hooks, called GLX functions, for attaching OpenGL to those windows. The Win32 API is used on Windows to create windows. OpenGL can be attached to these windows using the WGL API.

Because window creation and OpenGL attachment are platform-specific, there are a number of cross-platform tools that make it possible to write platform-neutral OpenGL code. FreeGLUT is the tool that these tutorials use, and it is included as part of the SDK in the source distribution. There are a number of other tools available. We will discuss many of the options here.

FreeGLUT.  FreeGLUT is based on the original GLUT, the OpenGL Utility Toolkit. You should never use GLUT; it is old and has not been updated in a decade. But FreeGLUT is 100% backwards compatible with it; any application that used GLUT can use FreeGLUT with no source code changes.

FreeGLUT creates and manages the window for the application. It provides callbacks so that the user can respond to various events. In these tutorials, the framework has initialized FreeGLUT and registered several standard callbacks, which each tutorial implements. There is a callback for when the display needs updating, when the user has resized the window, when the user has pressed a key, and when mouse input happens.

FreeGLUT can create windows or full-screen displays. It also has some limited support for menus. This does not allow you to create a menu bar, but it does allow you to create a right-click context menu.

FreeGLUT is a good tool for rapidly prototyping an effect. However, building a real application in it is problematic, particularly if you have specific timing needs. FreeGLUT owns the message processing loop; this limits your options for dealing with strict timing and so forth. FreeGLUT is good for demo programs and prototyping, but serious applications should avoid it.

FreeGLUT does have some text rendering functions, but these do not work when using shader-based rendering. If you are using a core OpenGL context, these functions will fail. They will also fail in compatibility contexts if you have a program object bound to the context.

FreeGLUT uses the X-Consortium license.

GLFW.  GLFW is an alternative to FreeGLUT. Like FreeGLUT, GLFW is fairly bare-bones. It provides a way to create windows or full-screen displays.

The biggest difference between them is that, while FreeGLUT owns the message processing loop, GLFW does not. GLFW requires that the user poll it to process messages. This allows the user to maintain reasonably strict timings for rendering. While this makes GLFW programs a bit more complicated than FreeGLUT ones (which is why these tutorials use FreeGLUT), it does mean that GLFW would be more useful in serious applications.

Additionally, GLFW offers more robust support in a number of areas. Both FreeGLUT and GLFW can create full-screen applications, but GLFW provides a means to query the available resolutions. They both offer time querying, but GLFW offers much higher resolution timers, while FreeGLUT timers only have millisecond resolution. They both offer support for joystick input, but GLFW allows the ability to query basic information about the joysticks (number of buttons and axes), as well as supporting an arbitrary number of buttons and axes.

Overall, it is a more game-centric API than FreeGLUT. One thing that is (currently) missing from GLFW is the ability to create an sRGB default framebuffer. GLFW uses the zLib license.

Multimedia Libraries.  A multimedia library is a library that handles, in a cross-platform way, graphics, sound, input, and other things. The impetus for all of these was DirectX, a Microsoft library that handles graphics, sound, input and a few other things for the purpose of improving the life of game developers. The purpose of DirectX was to be hardware-independent; code could be written against all graphics or sound hardware, and DirectX would sort out the details.

Cross-platform multimedia libraries do this as well, but they take things cross-platform. They generally support the big 3 operating systems (Windows, Linux, MacOSX), possibly also supporting BSD or various other shades of UNIX. Unlike DirectX, the multimedia libraries did not create their own 3D rendering system; they instead simply provide a way to use OpenGL.

The two biggest multimedia libraries are SDL (Simple Directmedia Layer) and SFML (Simple and Fast Multimedia Library). SDL is the older, but it is still receiving updates. It is a C library, so if you are allergic to C-isms, you may wish to avoid it. Work is being done on SDL 1.3, which will apparently have support for mobile platforms. SDL uses the zLib license.

SFML is a newer library, which has a C++ API. While SDL is one big library (and requires dependencies like DirectX on Windows), SFML is more of a choose-your-own package. The base package contains just input and the ability to create a window, while there are other packages that build upon this. Also SFML makes it possible to integrate SFML windows with other GUI toolkits (see below); this makes it easier to build non-gaming applications that use actual GUI tools. SFML uses the zLib license.

Allegro is a game-centric multimedia library. Version 5 has native support for OpenGL in its graphics subsystem. It uses a C interface. It also has a number of advanced 2D rendering functions. Allegro uses the giftware license, which is rather like the MIT license.

GUI Toolkits.  There are a number of cross-platform GUI libraries that deal with detailed window management, provide controls, and generally act like a full-fledged windowing system. Most of them have support for using OpenGL in one or more of their windows. Qt, wxWidgets, GTK, all have some form of OpenGL window that you can use.

Which window creation tools you use are entirely up to you; the possible needs that you might have are well beyond the scope of this book.

Function Loading

Once an OpenGL context has been created, one must then load OpenGL's functions. In a normal library, this would not actually be a step; those functions would have a header that you include and a library of some sort that you link to, either statically or dynamically. Due to various complexities around OpenGL, it cannot work that way on most platforms.

Therefore, the user must query the context itself for the functions to load. And OpenGL has many functions. So the common way to handle this is to use a library to do it for you.

GL Load.  This comes with the Unofficial OpenGL SDK. While most of the SDK is not intended for high-performance use, GL Load is still perfectly functional in that capacity. After all, this is generally a one-time initialization step, so performance is ultimately irrelevant.

GL Load works with core and compatibility contexts equally well. Indeed, unlike most OpenGL loading libraries, it separates not just core and compatibility headers, but it also separates headers by OpenGL version. So if you work in OpenGL 3.3, you won't see functions or enumerators from later versions (except when they are exposed as OpenGL extensions).

GL Load uses the MIT License.

GLEW.  GLEW (the OpenGL Extension Wrangler) is perhaps the most widely used OpenGL loading library. While it is technically intended for loading extension functions, it works just as well on the OpenGL core functions.

The principle downside of GLEW is that it does not work well with core contexts. There is some experimental support to make this work, but it is experimental. GLEW uses the MIT license.

GL3W.  GL3W is unique in that it is not technically a library. It is a Python script that downloads and parses a header file, which it uses to create a library. This allows it to be as up-to-date as the source file that it downloads. The downside is that the format of this source file may change, and if it does, it would break this tool.

GL3W is intended specifically for core contexts, and it does not work with compatibility or older OpenGL versions. Being a Python script, it requires a Python environment. Specifically it requires Python 2.6; it is unknown if it works with later Python versions. GL3W is public domain software.

Initialization

Once you have selected your tools of choice, the next step is to make them work. After downloading and compiling them, you will need to register them with your C/C++ build tool of choice. On Linux-platforms, you typically have some global registry for these things, but on Windows, things go where you put them.

How to use them depends on which tools you use. But the general idea for OpenGL context creation tools is that there will be some series of commands to supply parameters to the underlying system for context creation. And then a function is called to use those parameters to create the context. It is only after this process has successfully completed that one should call whatever initialization function the OpenGL function loading system uses. Your tools' documentation should explain this.

After doing both of these, you should be able to make OpenGL calls. The specifics on how to swap framebuffers (which is not part of the OpenGL API) is again left up to the window management tool.

Fork me on GitHub