Working with Glut


Delphi Glut Headers http://home.get2net.dk/mithrandir
SGI Glut Downloads http://reality.sgi.com/opengl/glut3/glut3.html
SGI Glut FAQ http://reality.sgi.com/mjk/glut3/glut-faq.html
Charlie's example programs on source forge.http://sourceforge.net/projects/elvenware

Glut is pronounced like the first syllable in gluttony.

Glut has two primary goals:

Glut allows you to simply and easily create windows, add simple controls such as menus, and handle basic user input. it is not, however, intended to be a cross platform library such as Qt. It is much simpler than a full blown GUI library. It is just a hand full of calls for creating simple applications

You have more power using a set of native APIs

The classic book on OpenGL, the OpenGL Programmer's Guide, uses Glut almost exclusively throughout. There is nothing rinkydink about using Glut, it's a good way to get some jobs done. It only fails you if you need to dig in deeply.

What you Need

You need to be sure the Glut DLL is on your system. C++ developers need Glut.h, which ships with C++Builder in the ../include/gl/ directory. Delphi programers need a translation of the Glut header file. The link at the top of this article shows how to get that file.

Getting Started

Glut programs can be very short and simple.

#include 
#include 
#include 
#pragma hdrstop

void Display(void)
{
  glClearColor(0,0,0,1);
  glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
    glVertex3f(-1.0,0.0,0.0);
    glVertex3f(0.0,1.0,0.0);
    glVertex3f(1.0,0.0,0.0);
  glEnd();
  glFlush ();
}

#pragma argsused
int main(int argc, char* argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE || GLUT_RGB);
  glutCreateWindow("Simple GLUT Application");
  glutDisplayFunc(Display);
  glutMainLoop();
  return 0;
}

The same code in Object Pascal:

program GlutBasics;

uses
  Windows, SysUtils, OpenGL,
  ElfGlut;

procedure Display; cdecl;
begin
  glClearColor(0.0,0.0,0.0,1.0);
  glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
    glVertex3f(-1.0,0.0,0.0);
    glVertex3f(0.0,1.0,0.0);
    glVertex3f(1.0,0.0,0.0);
  glEnd;
  glFlush ();
end;

begin
  if glutInit(MS_LIB) then begin
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow('A very simple Glut application');
    glutDisplayFunc(Display);
    glutMainLoop;
  end;
end.

In C, you pass in the parameters to main when you call glutInit:

glutInit(&argc, argv);

In Pascal, you pass in either MS_LIB or SGI_LIB:

if glutInit(MS_LIB) then begin 

If you are working in Linux, then you definitely should pass in SGI_LIB. I have done some work in Kylix with Glut, and it has gone fairly well.

Once you have initialized the system, you need to create your main window:

    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow('A very simple Glut application');

The parameter you pass into glutCreateWindow ends up as the caption to your window.

The next step is to declare your call back proceding for handling painting chores, and then to enter the main loop:

    glutDisplayFunc(Display);
    glutMainLoop;

Handling Resize Events

Here is the C++Builder source:

#ifdef _WIN32
#include 
#endif

#include 
#include 
#include 
void ErrorCheck(char* s)
{
  GLenum errorCode;
  errorCode = glGetError();
  if (errorCode != GL_NO_ERROR)
    printf("Error in %s %s", s, gluErrorString(errorCode));
}

void Reshape(int w, int h)
{
  glViewport(0, 0, w, h);       /* Establish viewing area to cover entire window. */
  glOrtho(-1, 1, -1, 1, -1, 1);
}

void Display(void)
{
  glClearColor(0.8,0.8,0.9,1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
     ErrorCheck("Display middle");
     glColor3f(1.0,0.0,0.0);  glVertex3f(-1.0, -1.0, 0.0);
     glColor3f(0.0,1.0,0.0);  glVertex3f(0.0, 1.0, 0.0);
     glColor3f(0.0,0.0,1.0);  glVertex3f(1.0, -1.0, 0.0);
  glEnd();
  glFlush();
  ErrorCheck("Display End");
}

#pragma argsused
int main(int argc, char* argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  glutInitWindowSize(640, 480);
  glutInitWindowPosition(250, 250);
  glutCreateWindow("Try resizing this window");
  glutDisplayFunc(Display);
  glutReshapeFunc(Reshape);
  ErrorCheck("About to start loop");
  glutMainLoop();

  return 0;
}

Here is the Pascal source:

program GlutReshape;
uses
  Windows, SysUtils, OpenGL,
  ElfGlut;

procedure Display; cdecl;
begin
  glClearColor(0.0,0.0,0.0,1.0);
  glClear(GL_COLOR_BUFFER_BIT);
  glBegin(GL_TRIANGLES);
    glColor3f(1.0,0.0,0.0); glVertex3f(-1.0,0.0,0.0);
    glColor3f(0.0,1.0,0.0); glVertex3f(0.0,1.0,0.0);
    glColor3f(0.0,0.0,1.0); glVertex3f(1.0,0.0,0.0);
  glEnd;
  glFlush ();
end;

procedure Reshape(w, h: Integer); cdecl;
begin
  glViewport(0, 0, w, h);
  glOrtho(-1, 1, -1, 1, -1, 1);
end;

begin
  if glutInit(MS_LIB) then begin
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow('A very simple Glut application');
    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutMainLoop;
  end;
end.

The major difference in this code from the earlier versions comes in the main code block, where there is a call to glutReshapeFunc:

glutReshapeFunc(Reshape);

This function tells glut what function of yours to call when there is a resize event. It is very much like setting up an OnResize event in C++Builder or Delphi. The method you create will be passed the current width and height of the window that was resized. In Delphi, you must explicitly the function to use the cdecl calling convention

Here is the Reshape method itself:

procedure Reshape(Width, Height: Integer); cdecl;
begin
  glViewport(0, 0, Width, Height);
  glOrtho(-1, 1, -1, 1, -1, 1);
end;

On the main page of this document you can find information on Ortho and ViewportglViewport and glOrtho.