An Introduction to OpenGL Programming

OpenGL is a well-known standard for generating 3-D as well as 2-D graphics that is extremely powerful and has many capabilities. OpenGL is defined and released by the OpenGL Architecture Review Board (ARB).

This article is a gentle introduction to OpenGL that will help you understand drawing using OpenGL.

The latest version of OpenGL at the time of this writing is 4.4, which uses a different technique for drawing from the one presented here. Nevertheless, the purpose of this article is to help you understand OpenGL philosophy, not teach you how to code using the latest OpenGL version. Therefore, the presented source code can be run on Linux machines that have an older OpenGL version installed.

Installing OpenGL

If you run the following command on a Debian 7 system to find all packages that contain the word "opengl", you'll get plenty of output (Figure 1):


$ apt-cache search opengl

Figure 1. Running apt-cache search opengl

There are many free OpenGL implementations for Linux, but you need only one. I installed FreeGLUT, because it is the most up to date. FreeGLUT is an open-source alternative to the OpenGL Utility Toolkit (GLUT) library:


root@mail:~# apt-get install freeglut3 freeglut3-dev libglew-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following package was automatically installed 
 and is no longer required:
  fonts-liberation
Use 'apt-get autoremove' to remove it.
The following extra packages will be installed:
  libgl1-mesa-dev libglu1-mesa-dev libice-dev libpthread-stubs0
  libpthread-stubs0-dev libsm-dev libx11-dev libx11-doc 
  libxau-dev libxcb1-dev libxdmcp-dev libxext-dev libxt-dev 
  mesa-common-dev x11proto-core-dev x11proto-input-dev 
  x11proto-kb-dev x11proto-xext-dev xorg-sgml-doctools xtrans-dev
Suggested packages:
  libice-doc libsm-doc libxcb-doc libxext-doc libxt-doc
The following NEW packages will be installed:
  freeglut3 freeglut3-dev libgl1-mesa-dev libglu1-mesa-dev 
  libice-dev libpthread-stubs0 libpthread-stubs0-dev libsm-dev 
  libx11-dev libx11-doc libxau-dev libxcb1-dev libxdmcp-dev 
  libxext-dev libxt-dev mesa-common-dev x11proto-core-dev 
  x11proto-input-dev x11proto-kb-dev x11proto-xext-dev 
  xorg-sgml-doctools xtrans-dev
0 upgraded, 22 newly installed, 0 to remove and 0 not upgraded.
Need to get 7,651 kB of archives.
After this operation, 24.9 MB of additional disk space 
 will be used.
Do you want to continue [Y/n]?

You also will need a C++ compiler to compile the code.

Finally, you may need to install the mesa-utils package in order to be able to use the glxinfo command:


# apt-get install mesa-utils

The glxinfo command displays useful information about your OpenGL installation, as you can see in the following output:


...
GLX version: 1.4
GLX extensions:
    GLX_ARB_get_proc_address, GLX_ARB_multisample, 
    GLX_EXT_import_context, GLX_EXT_texture_from_pixmap, 
    GLX_EXT_visual_info, GLX_EXT_visual_rating,
    GLX_MESA_copy_sub_buffer, GLX_MESA_multithread_makecurrent,
    GLX_OML_swap_method, GLX_SGIS_multisample, GLX_SGIX_fbconfig,
    GLX_SGIX_pbuffer, GLX_SGI_make_current_read
OpenGL vendor string: VMware, Inc.
OpenGL renderer string: Gallium 0.4 on llvmpipe 
  (LLVM 3.4, 128 bits)
OpenGL version string: 2.1 Mesa 10.1.3
OpenGL shading language version string: 1.30
OpenGL extensions:
...

Mesa is a 3-D graphics library with an API that is so very similar to OpenGL's, it is pretty much indistinguishable.

OpenGL Pipeline

Figure 2—taken from the OpenGL Shading Language book (aka "The Orange Book")—shows the programmable OpenGL pipeline with the vertex and fragment processors. As you can imagine, the OpenGL pipeline is complex, but you do not have to understand it fully in order to be able to use OpenGL. The Pipeline shows how OpenGL operates in the background. Newer versions of the OpenGL Pipeline are even more complex!

Figure 2. OpenGL Architecture

OpenGL is a big state machine. Most calls to OpenGL functions modify a global state that you cannot access directly.

The OpenGL Shading Language code that is intended for execution on one of the OpenGL programmable processors is called a Shader. The OpenGL Shading Language has its roots in C (presenting the OpenGL Shading Language is beyond the scope of this article).

OpenGL does not define a windowing layer, because it tries to be platform-neutral and leaves this functionality to the operating system. The OS must provide a rendering context that accepts commands as well as a framebuffer that keeps the results of the drawing commands.

Matrix Algebra is extensively used in 3-D graphics, so it is good for you to know how to add, multiply, subtract and divide matrices, although you will not need to code such operations yourself. It also is useful to become familiar with 3-D coordinates and be able to sketch on paper the 3-D scene you are trying to draw.

Drawing a Triangle

Now it's time for some real OpenGL code. The code in Listing 1, when executed, draws a triangle on-screen using OpenGL.

Listing 1. triangle.cc


// Programmer: Mihalis Tsoukalos
// Date: Wednesday 04 June 2014
//
// A simple OpenGL program that draws a triangle.

#include "GL/freeglut.h"
#include "GL/gl.h"

void drawTriangle()
{
    glClearColor(0.4, 0.4, 0.4, 0.4);
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3f(1.0, 1.0, 1.0);
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);

        glBegin(GL_TRIANGLES);
                glVertex3f(-0.7, 0.7, 0);
                glVertex3f(0.7, 0.7, 0);
                glVertex3f(0, -1, 0);
        glEnd();

    glFlush();
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OpenGL - Creating a triangle");
    glutDisplayFunc(drawTriangle);
    glutMainLoop();
    return 0;
}

The code in Listing 1 for setting up OpenGL is large, but you will have to learn it only once.

On a Debian 7 system, the following command compiled the triangle.cc OpenGL program without any error messages:


$ g++ triangle.cc -lglut -o triangle

On an Ubuntu Linux system, the same command produced the following error messages:


/usr/bin/ld: /tmp/ccnBP5li.o: undefined reference to symbol 
 ↪'glOrtho'
//usr/lib/x86_64-linux-gnu/mesa/libGL.so.1: error adding 
//symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

The solution is to compile the triangle.cc program by linking the executable to an additional library (-lGL):


mtsouk@mtsouk-VirtualBox:/media/sf_OpenGL.LJ/code$ g++ 
 ↪triangle.cc -lglut -lGL -o triangle

The libGL.so library accepts OpenGL commands and makes sure that they are put on the screen in some way. If your graphics card does not have 3-D acceleration, libGL contains a software renderer that gives a 2-D image as output to the X Window System. This is the case with Mesa. libGL also can pass the OpenGL information to the X Window System, if the GLX extension is present. Then, the X Window System can do software rendering with the help of Mesa or use hardware acceleration.

The output from the executable will produce the triangle shown in Figure 3. The correct compilation of triangle.cc is proof that your Linux system can be used for developing OpenGL applications.

Figure 3. Drawing a Triangle Using OpenGL

______________________