Help end child hunger

GLUT and FreeGLUT

 
Prev: Libs that work great with OpenGL Next: Error Tracking in OpenGL
 

GLUT was conceived by Mark Kilgard with the goal of providing a simple, yet powerful enough, toolkit to deal with the intricacies of the windowing system when building OpenGL applications.

In my opinion GLUT was a very effective solution and completely fits the bill. As far as I know, GLUT is still the simplest toolkit around and yet it does most of what is needed for simple prototypes.

GLUT however is not free of criticism. Complaints about the lack of control on the event loop are abundant on the web. Mark’s position was that adding the required control would bring unnecessary complexity, at least that is what is claimed in here.

Furthermore GLUT last release was back in the last century… 🙂

Things have evolved a little since then and some features are missing. For instance GLUT does not allow context setting, does not contemplate the mouse wheel, and multisampling, although in GLUT’s spec, is not implemented.

GLUT is not open source hence it could not be modified, so GLUT clones have appeared. These kept the API (all gluts functions are usually implemented exactly with the same name) but improved and extended it to address the above mentioned issues.

Two of the most common GLUT replacements are OpenGLUT and freeGLUT. These are two open source projects. freeGLUT seems more mature and more up to date, at least based on the sourceforge dates for the last updates. In here we are going to focus on freeglut.

All the stuff in the GLUT tutorial is exactly the same, apart from one detail when using subwindows. Even the include is the same if you use glut.h from the freeglut distribution. The main differences that I found are as follows:

Multisampling

Freeglut follows GLUT’s spec on multisampling but, as opposed to GLUT, it actually implements it.

To setup multisampling just add the flag GL_MULTISAMPLE to glutInitDisplayMode as follows:

glutInitDisplayMode(GLUT_DEPTH | 
                    GLUT_DOUBLE | 
                    GLUT_RGBA | 
                    GLUT_MULTISAMPLE);

Then to activate multisampling all that is required is:

glEnable(GL_MULTISAMPLE)

Although multisampling is not the most sophisticated anti-aliasing method it does visually enhance your renderings with virtually no cost regarding implementation.

The first image shows a rendering without multisampling, the second image with multisampling enabled.

Game Mode

Freeglut seems to only work when the GameMode resolution is set to the full screen. My attempts at setting the GameMode to a lower resolution failed 🙁

Also I was only able to set GameMode when I provided all four fields in mode string. Leaving one field out did not change from window mode to GameMode.

Furthermore, freeglut seems to loose the window settings when returning from the GameMode. Hence a call to glutSetWindow is required, as shown in the code snippet below:

char mode_string[20];
sprintf(mode_string,"%dx%d:32@60", glutGet(GLUT_SCREEN_WIDTH),
				   glutGet(GLUT_SCREEN_HEIGHT));
glutGameModeString(mode_string);

...

// When leaving GameMode freeglut requires 
// setting the window again

if (glutGameModeGet(GLUT_GAME_MODE_ACTIVE) != 0) {
			glutLeaveGameMode();
			glutSetWindow(mainWindow);
	}

MouseWheel

The mouse wheel is not contemplated in GLUT’s spec. Freeglut extends the original spec and it includes the possibility to register a callback function for the mouse wheel.

The registration function is:

glutMouseWheelFunc(myMouseWheel Func)

where my mouse wheel is defined as:


void glutMouseWheel(int wheel, int direction, int x, int y)

Params:

  • wheel: the wheel number, if the mouse has only a wheel this will be zero.
  • direction: a +/- 1 value indicating the wheel movement direction
  • x, y: the window mouse coordinates

This function will be called when the mousewheel moves for each notch. Note the mouse wheel still functions as the middle button, but those events are treated as regular press and release mouse button events.

Main Loop

Freeglut provides full control of the event loop. Let’s explore some of the available features. One of the major complaints about the original GLUT was that when a window was closed the application was shutdown automatically. This prevented the execution of cleanup code, or could cause problems in multiple window setups.

With freeglut it is possible to specify what happens when a user closes a window. The flag/option GLUT_ACTION_ON_WINDOW_CLOSE is used for this purpose. The available options are:

  • GLUT_ACTION_GLUTMAINLOOP_RETURNS: The application exits the main loop when the window is closed and execution continues
  • GLUT_ACTION_CONTINUE_EXECUTION: The application continues as if nothing happened. This is useful for multiple window setups. If the application has a single window then this option behaves exactly as the first option.

freeglut has added a function to GLUT’s original spec:

glutSetOption(GLenum option_flag, int value)

Consider the following snippet of code:

...
// Note: glutSetOption is only available with freeglut
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
              GLUT_ACTION_GLUTMAINLOOP_RETURNS);

glutMainLoop();
printf("I'm out\n");

With GLUT, the printf would never be executed. With freeglut the main loop terminates and the application regains control, hence the printf will be executed.

Freeglut provides yet another useful function to end the event loop:

glutLeaveMainLoop()

In the freeglut’s spec it states that

If the GLUT_ACTION_ON_WINDOW_CLOSE option has been set to GLUT_ACTION_CONTINUE_EXECUTION, control will return to the function which called glutMainLoop; otherwise the application will exit.

However, in my tests I’ve noticed that control is always returned to the function that called glutMainLoop, regardless of the setting used for GLUT_ACTION_ON_WINDOW_CLOSE.

A possible usage of this function is when the user presses the ESC key. So instead of having:

void processKeys(unsigned char key, int xx, int yy)
{
	switch(key) {

		case 27: // QUIT
			exit(0);
	}
}

one can write:

void processKeys(unsigned char key, int xx, int yy)
{
	switch(key) {

		case 27: // QUIT
			glutLeaveMainLoop();
	}
}

Be careful when using this function. In my tests freeglut continued to process the events that were already queued so performing any cleanup before actually getting out of the event loop could crash the application.

Freeglut even provides a callback registration for when a window is closed:

glutCloseFunc ( void( *callback )( void ))

Use this function to free your OpenGL resources.

Finally freeglut allows us to write our own event loop cycle. The function glutMainLoopEvent processes a single iteration of the event loop. There seems to be little documentation regarding what is “an iteration” but from what I was able to gather from the web it seems that “an iteration” consists of executing all the queued events.

Using this function with the idle func does not seem to work very well. If you want to write your own event loop I suggest you drop the idle func and use the following event processing cycle:

while (!loopExit) {

	...
	glutMainLoopEvent();
	renderScene();
	...
}

OpenGL Context Setting

Another benefit of using freeglut is the ability to create OpenGL contexts with profiles. This is achieved with the following functions:

glutInitContextVersion (int majorVersion, int minorVersion)
glutInitContextProfile ( int profile)
glutInitContextFlags ( GLuint flags)

The possible values for the profile are: GLUT_CORE_PROFILE and GLUT_COMPATIBILITY_PROFILE.

Flags can be set to GLUT_DEBUG and/or GLUT_FORWARD_COMPATIBLE.

For instance to set a compatibility context with OpenGL 3.3 just write:

glutInitContextVersion (3,3);
glutInitContextProfile ( GLUT_CORE_PROFILE );

To get a core OpenGL 4.1 context with Debug write:

glutInitContextProfile (GLUT_CORE_PROFILE );
glutInitContextFlags(GLUT_DEBUG);

 

Prev: Libs that work great with OpenGL Next: Error Tracking in OpenGL
 

  2 Responses to “GLUT and FreeGLUT”

  1. I must use own loop like that
    while (!loopExit) {


    glutMainLoopEvent();
    renderScene();

    }
    glutMainLoopEvent works only one time. What the content of renderScene?

  2. for anyone else trying to do multisampled snowmen, you’ll have to include glew.h for it to work. make sure to have it as the first include, or your compiler will asplode in fury. 🙂

    eg (have swapped angle brackets for normal brackets, seen a few comment examples elsewhere on this site get chewed up by wordpress)

    #include (GL/glew.h)
    #ifdef __APPLE__
    #include (GLUT/glut.h)
    #else
    #include (GL/glut.h)
    #endif

    etc…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: