ISU Game Developers Club
General Information
Mailing Lists

Open Privateer


Project Page
Lab Sessions
CVS Access
Subversion Access


Configuring the Environment

  • Open Visual NET
  • Download and extract GLUT from
  • In NET, click Tools | Options | Projects | VC++ Directories
  • Change the "Show directories for" dropdown to "Include Files"
  • Add the GLUT directory to the list

Creating the Project

  • In NET, click File | New | Project
  • Under Visual C++ Projects, choose Win32 project
  • Give your project a name, and for the location, select your desktop
  • After clicking OK, go under "Application Settings" and select Console Application
  • Make sure "Empty project" is checked
  • When you click Finish, NET should create a new project for you
  • Right-click on Source Files and choose "Add Existing Item"
  • Find the GLUT .lib file that you downloaded and add it to the project
  • Then right-click on Source Files and choose "Add New Item"
  • Enter a name for your main source file and add it to the project

Now we can begin writing code! The following is about where we left off last time. Copy the source into your .cpp, or write it again yourself, if you wish.

#include <math.h>
#include <stdlib.h>
#include <glut.h>

// this gets called when we want to redraw the window
void display() {
        // clear the framebuffer of stuff we have drawn in the past
        // set up our screen projection so that our window has coordinates from
        // -1 to 1 (left to right) and -1 to 1 (top to bottom)
        glOrtho(-1, 1, 1, -1, -1, 1);
        // our view projection is a single rotation, based on the number
        // of milliseconds elapsed since the beginning of program
        // execution
        glRotatef(glutGet(GLUT_ELAPSED_TIME) / 10, 0, 0, 1);
        glColor3f(1, 0, 0); // red
        glVertex2f(0, -1);
        glColor3f(0, 1, 0); // green
        glVertex2f(-1, 1);
        glColor3f(0, 0, 1); // blue
        glVertex2f(1, 1);
        // swap the backbuffer with the frontbuffer

// this gets called whenever GLUT has nothing else to do
void idle() {
        // let's just redraw the screen

int main(int argc, char** argv) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
        glutCreateWindow("My GLUT Test");
        // callback setup

Keyboard Input

Now let's add some keyboard input to the application. To get the framework set up and add quit functionality... Add the following line to your callback setup.


You will also need a function that looks like the following:

void keypress(unsigned char key, int x, int y) {
        // key is the ASCII value of the key that is pressed...
        // so it is 'a' if the A key is pressed
        if (key == 27) {  // ESCAPE

Now try pressing escape when your program is running. :)

Try adding support for new keys to the keypress function. Maybe make the A and S keys move the triangle to the left and to the right with glTranslatef().

Mouse Input

Go to and try to figure out how to use the mouse callback. glutMouseFunc, glutMotionFunc, and glutPassiveMotionFunc are what you want.


I have written an image loading library called Corona ( It makes loading images very easy, so we'll use it.

  • Download the Win32 binary release to your desktop and extract it
  • Add corona.lib to your project
  • Add the corona/include directory to the VC++ Include directories list
  • Add corona.h to your #includes at the top of your source file.
  • Add "#include " to your #includes
  • Also add "#include " to your #includes
  • Add the line "using namespace corona;" beneath it
  • Add the following code to the top of your program (underneath the includes)

int GetNextPowerOf2(int n) {
        int i = 1;
        while (i < n) {
                i *= 2;
        return i;

inline void ThrowTextureError(const std::string error) {
        throw std::runtime_error(error.c_str());

typedef unsigned int u32;

class Texture
        Texture(const std::string& filename) {
                std::auto_ptr<Image> image(
                OpenImage(filename.c_str(), FF_AUTODETECT, PF_R8G8B8A8));
                if (!image.get())
                        ThrowTextureError("Could not load image '" + filename + "'");
                // remember the actual size of the image so we know how much of the
                // texture to use when calculating texture coordinates
                int  real_width  = image->getWidth();
                int  real_height = image->getHeight();
                u32* real_pixels = (u32*)image->getPixels();
                // allocate power of two buffer to store actual texture memory
                // and zero it
                int tex_width  = GetNextPowerOf2(real_width);
                int tex_height = GetNextPowerOf2(real_height);
                u32* buffer = new u32[tex_width * tex_height];
                memset(buffer, 0, tex_width * tex_height * sizeof(u32));
                /// @todo  make sure we don't try to create a texture that
                ///        larger than what the video card can handle...
                ///        3Dfx cards can only handle 256*256 tex's
                // copy our image pixels into the texture buffer
                for (int row = 0; row < real_height; ++row)
                        memcpy(buffer + tex_width * row,
                        real_pixels + real_width * row,
                        real_width * sizeof(u32));
                mRealWidth  = float(real_width)  / tex_width;
                mRealHeight = float(real_height) / tex_height;
                glGenTextures(1, &mTexture);
                glBindTexture(GL_TEXTURE_2D, mTexture);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
                tex_width, tex_height,
                0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                /// @todo  use a boost scoped array
                delete[] buffer;
        ~Texture() {
                glDeleteTextures(1, &mTexture);
        void bind() {
                glBindTexture(GL_TEXTURE_2D, mTexture);
        void drawRectangle(int x1, int y1, int x2, int y2) {
                glTexCoord2f(0,          0);           glVertex2i(x1, y1);
                glTexCoord2f(mRealWidth, 0);           glVertex2i(x2, y1); 
                glTexCoord2f(mRealWidth, mRealHeight); glVertex2i(x2, y2); 
                glTexCoord2f(0,          mRealHeight); glVertex2i(x1, y2); 
        GLuint mTexture;
        float mRealWidth;
        float mRealHeight;

Now, to get a textured image to load in your program, you have to enable a GL state in your main() function.

Add the line "glEnable(GL_TEXTURE_2D);" before the glutMainLoop() call.

Then try making a global variable (below the Texture class) like this:

Texture* gTexture; 

In main(), after your new glEnable() call, do this:

gTexture = new Texture("image.bmp");

In display(), before the triangle, add the following lines:

glColor3f(1, 1, 1);  // reset the color multiplier to white (i.e. show all color elements of the image)
gTexture->drawRectangle(-1, -1, 1, 1);

Of course, this means you need an image image.bmp on your computer! Go look on google for some image and stick in the same directory as your executable.

-- BenScott - 26 Dec 2002