Introduction to the GLUT

The GLUT is a set of high level software tools that provide programmer access to openGL while avoiding the details of a specific GUI. This tutorial uses the latest version of the GLUT available at the GLUT HomePage. A local copy of the GLUT 3 Specification is avaliable here.

If you are creating openGL applications in Linux or for the SGIs you can find supporting information at the GLUT HomePage including all source code and bindings. 

If you are running windows and Visual Studio.NET then you can download the necessary .dll, include and .lib files here.  Place the .dll files into Windows/System32 folder, the .lib files into the .lib folder inside C://Program Files/Microsoft Visual Studio 8/VC/lib/.  The .h files in the gl folder must be placed inside the include/gl folder.  Replace existing files only if they are older than the downloaded files.

Getting Started (for PCs only)

A Simple Example Program

Before trying to write our own, lets take a look at a simple example openGL program.  Each line of the main( ) function is explained below this source code.  We will study the details of the openGL calls in the function render( ) a bit later.

void glutInit(int argc, char **argv)

Initializes GLUT and should be called before any OpenGL functions: glutInit( ) takes the arguement from main( ) and can use them in an implmementation-dependent manner.

   void main(int argc, char **argv)
   {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
   }
 


 
void glutInitDisplayMode(unsigned int mode)

Requests a display with the properties in mode.  The values of mode are combined by using the logical OR (i.e. | ), such as color model (GLUT_RGB, GLUT_INDEX) and buffering of color buffers (GLUT_SINGLE, GLUT_DOUBLE).

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 


 
void glutInitWindowPosition(int x, int y)

Specifies the top-left corner of the window, measured in pixels, from the top-left corner of the screen.

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 


 
void glutInitWindowSize(int width, int height)

Specifies the initial height and width, in pixels, of the iwndow on the screen.

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 


 
int glutCreateWindow(*char title)

Creates a window on the screen with the title given by the argument.  The function returns an integer that can be used to refer to the window in multiwindow situations.

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 


 
void glutDisplayFunc(void (*func) (void))

The function func( ) is called each time there is a display callback.

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 


 
void glutMainLoop( )

Causes the program to enter an event-processing loop.  this statement should be the last one in the main( ) function.

     void main(int argc, char **argv)
     {

      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
      glutInitWindowPosition(100,100);
      glutInitWindowSize(500,500);
      glutCreateWindow("My First openGL Program");
      glutDisplayFunc(render);
      glutMainLoop();
     }
 



Compile and Run

Create a Windows32 console application and run this source code.  If everything works correctly you should see a Console Window and a Graphics Window similar to the following:


Creating Simple 2D Line Drawings

Modify this program so that it draws black lines on a white background (this will save a lot of ink when we print hardcopies).  Add the following two lines to the top of the render( ) function. You do not have to include the comments (of course).

glClearColor(1.0,1.0,1.0,1.0); // sets the clear color to opaque white  (R,G,B,opacity)
glColor3f(0.0,0.0,0.0);        // sets the drawing color to black
  
 
#include "stdafx.h"
#include <gl/glut.h>

     void render(void) {
       glClearColor(1.0,1.0,1.0,1.0);
       glColor3f(0.0,0.0,0.0);
       glClear(GL_COLOR_BUFFER_BIT);
       glBegin(GL_LINE_LOOP);
          glVertex3f(-0.8,-0.8,0.0);
          glVertex3f( 0.8,-0.8,0.0);
          glVertex3f( 0.8, 0.8,0.0);
          glVertex3f(-0.8, 0.8,0.0);
       glEnd();
       glFlush();
    }

     void main(int argc, char **argv) {
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
       glutInitWindowPosition(100,100);
       glutInitWindowSize(500,500);
       glutCreateWindow("My First openGL Program");
       glutDisplayFunc(render);
       glutMainLoop();
    }


Sample Problems

1.  Write an openGL program to draw an nxn array of boxes (let n be even).  The array should occupy apx. 90% of the graphics window.  For now you may hardwire the value of n into your source code, but the program should be able to draw the array for any value of n by changing only this value and recompiling.  The separation between the boxes should be apx. 20% of the box size.  See examples below:
 

2.  Write an openGL console application to draw a recursive tree as shown in the examples below.  Your program should permit the user to enter the initial stem length, the decriment in stem length (for each successive level of recursion) and the angle between branches.  

 
 Sneak Preview

We will be able to extend our openGL programs into three dimensions with color and animations quite easily.  For a preview, build and execute an openGL program using the sample code below.

// rotate_triangles.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<gl/glut.h>

float angle = 0.0;

void changeSize(int w, int h) {

 // avoid divide by zero for small windows
 if(h == 0)
  h = 1;

 float ratio = 1.0* w / h;

 // Reset the coordinate system before modifying
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();

 // Set the viewport to be the entire window
    glViewport(0, 0, w, h);

 // Set the correct perspective.
 gluPerspective(45,ratio,1,1000);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 gluLookAt(0.0,0.0,5.0, 
        0.0,0.0,-1.0,
     0.0f,1.0f,0.0f);
 

}
 

void rotate_triangle(void) {
    glClearColor(1.0,1.0,1.0,1.0);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glPushMatrix();
 glRotatef(angle,0.0,1.0,0.0);
 glBegin(GL_TRIANGLES);
        glColor3f(1.0,0.0,0.0);
  glVertex3f(-0.5,-0.5,-0.2);
  glVertex3f(0.5,0.0,-0.2);
  glVertex3f(0.0,0.5,-0.2);
        glColor3f(0.0,1.0,0.0);
  glVertex3f(0.8,0.3,0.0);
  glVertex3f(-0.4,0.0,0.0);
  glVertex3f(0.0,-0.6,0.0);
        glColor3f(0.0,0.0,1.0);
  glVertex3f(-0.9,0.7,0.8);
  glVertex3f(-0.6,-0.9,-0.8);
  glVertex3f(-0.8,0.3,0.8);
 glEnd();
 glPopMatrix();
 angle++;
 glutSwapBuffers();
}

void main(int argc, char **argv) {
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowPosition(100,100);
 glutInitWindowSize(320,320);
 glutCreateWindow("3D Tech - GLUT Tutorial");
 glutDisplayFunc(rotate_triangle);
 glutIdleFunc(rotate_triangle);
 glutReshapeFunc(changeSize);
 glutMainLoop();
}


Using MouseAction and glutFullScreen

Sometimes we will want to view our images in full screen mode.  The command glutFullScreen() resizes the graphics window to fill the screen of the current display device.  Note that the aspect ratio of the screen may change your image shape unless your drawing functions take this into account.  You can use glutReshapeWindow( , ) to convert for full screen to any other size.  The program below is a simple example of how to use glutFullScreen() and the MouseAction features.  Don't worry about what is being drawn in the display( ).

// example of MouseAction and glutFullScreen

#include "stdafx.h"
#include <iostream>
#include <GL/glut.h>
#include <math.h>

 GLfloat yang = 0.2;
 GLfloat r,g,b = 0.5;
 GLfloat p,q   = 0.5;
 int fullscreen = 1;

 void MouseAction(int the_button, int button_state, int x, int y){
         if (the_button==GLUT_LEFT_BUTTON && button_state==GLUT_DOWN){
            if (fullscreen==1){
                 glutReshapeWindow(640,480);
            }else{
                glutFullScreen();
            }
            fullscreen = 1-fullscreen;
    }
 }

 void display() 
 { 
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); 
    r=r+(((float)rand()/(float)RAND_MAX)*0.05-0.025);
    if (r<0.0) r=0.0;
    if (r>1.0) r=1.0;
    g=g+(((float)rand()/(float)RAND_MAX)*0.05-0.025);
    if (g<0.0) g=0.0;
    if (g>1.0) g=1.0;
    b=b+(((float)rand()/(float)RAND_MAX)*0.05-0.025);
    if (b<0.0) b=0.0;
    if (b>1.0) b=1.0;
    p=p+(((float)rand()/(float)RAND_MAX)*0.05-0.025);
    if (p<0.0) p=0.0;
    if (p>1.0) p=1.0;
    q=q+(((float)rand()/(float)RAND_MAX)*0.05-0.025);
    if (q<0.0) q=0.0;
    if (q>1.0) q=1.0;
    glBegin(GL_POLYGON); 
       glColor3f(r,1-b,0.0); 
       glVertex2f(-1.0,-1.0);
       glColor3f(0,q-r,q);
       glVertex2f(-1.0,0.0);
       glColor3f(0.0,g,0.0); 
       glVertex2f(-1.0,1.0);
       glColor3f(0.0,p,1.0-p);
       glVertex2f(0.0,1.0);
       glColor3f(b,r,g);
       glVertex2f(1.0,1.0);
       glColor3f(q,0.0,r);
       glVertex2f(1.0,0.0);
       glColor3f(1.0-b,0.0,b); 
       glVertex2f(1.0,-1.0);
       glColor3f(g,g,1.0-b);
       glVertex2f(0.0,-1.0);
    glEnd(); 
    glutSwapBuffers();
    glFlush();
    glutMouseFunc(MouseAction);
 } 

 void init() 
 { 
    glClearColor(1.0,1.0,1.0,1.0); 
    glMatrixMode(GL_PROJECTION); 
    gluOrtho2D(-1.0, 1.0, -1.0, 1.0); 
 } 
  

 void main(int argc, char** argv) 
 { 
    glutInit(&argc,argv); 
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(400,400); 
    glutInitWindowPosition(0,0); 
    glutCreateWindow("PSI 01");
    glutFullScreen();
    glutDisplayFunc(display); 
    glutIdleFunc(display);
    init(); 
    glutMainLoop(); 
 }

Animation

http://www.lighthouse3d.com/opengl/glut/


OK, so far so good. We have an OpenGL window with a white triangle. Nothing very exciting, but hey, its a start. Now to complete this part of the GLUT tutorial lets have that triangle spinning.

Lets go back to the main function and add some extra stuff. First lets tell GLUT that we want a double buffer. Double buffering allows for smooth animation by keeping the drawing in a back buffer and swapping the back with the front buffer (the visible one) when the rendering is complete. Using double buffering prevents flickering.


    
        ...
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        ...
 

 

The second thing we must do is to tell GLUT that when the application is idle the render function should be called. This causes GLUT to keep calling our rendering function therefore enabling animation. GLUT provides a function, glutIdleFunc, that lets you register a callback function to be called when the application is idle.


void glutIdleFunc(void (*func)(void));

Parameters:

func - The name of the function that will be called whenever the application is idle.



In our case, when the application is idle we want to call the previously defined function that does the actual rendering: renderScene. OK, so the main function now looks like this:


    
void main(int argc, char **argv) {
        glutInit(&argc, argv);
        
        // This is where we say that we want a double buffer
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        
        glutInitWindowPosition(100,100);
        glutInitWindowSize(320,320);
        glutCreateWindow("3D Tech- GLUT Tutorial");
        glutDisplayFunc(renderScene);
        
        // here is the setting of the idle function
        glutIdleFunc(renderScene);
        
        glutReshapeFunc(changeSize);
        glutMainLoop();
}
 

 

Afterwards, we go and change the rendering itself. First lets declare a floating point variable angle, and initialize it to 0.0 . Then lets add the necessary stuff to the renderScene function.


    
float angle=0.0;
 
void renderScene(void) {
 
        // notice that we're now clearing the depth buffer 
        // as well this is required, otherwise the depth buffer 
        // gets filled and nothing gets rendered. 
        // Try it out, remove the depth buffer part.
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // save the previous settings, in this case save 
        // we're refering to the camera settings.
        glPushMatrix();
        
        // Perform a rotation around the y axis (0,1,0) 
        // by the amount of degrees defined in the variable angle
        glRotatef(angle,0.0,1.0,0.0);
        glBegin(GL_TRIANGLES);
               glVertex3f(-0.5,-0.5,0.0);
               glVertex3f(0.5,0.0,0.0);
               glVertex3f(0.0,0.5,0.0);
        glEnd();
        
        // discard the modelling transformations
        // after this the matrix will have only the camera settings.
        glPopMatrix();
        
        // swapping the buffers causes the rendering above to be 
        // shown
        glutSwapBuffers();
        
        // finally increase the angle for the next frame
        angle++;
}


The glutSwapBuffers function cause the front and back buffers to switch thereby showing what was previously drawn in the back buffer. The syntax is as follows:


void glutSwapBuffers();


There you have it, a spinning triangle You may download the VC project here (glut2.zip). Isn't it great? OK, ok...but I warned you, no fancy stuff in here, keeping the code to the minimum and focusing on GLUT is the way to learn this!