Something More for Research

Explorer of Research #HEMBAD

OpenGL program Lesson 1: Basic Shapes

Posted by Hemprasad Y. Badgujar on October 1, 2012

Lesson 1: Basic Shapes

Try it Out

Let’s take a look at our first OpenGL program. download the “basic shapes” program, and compile and run it (details on how to do that can be found in “Part 0: Getting OpenGL Set Up”). Take a look at it, and hit ESC when you’re done. It should look like the following image:


Overview of How the Program Works

How does the program work? The basic idea is that we tell OpenGL the 3D coordinates of all of the vertices of our shapes. OpenGL uses the standard x and y axes, with the positive x direction pointing toward the right and the positive y direction pointing upward. However, in 3D we need another dimension, the z dimension. The positive z direction points out of the screen.

AxesHow does OpenGL use these 3D coordinates? It simulates the way that our eyes work. Take a look at the following picture.

EyeOpenGL converts all of the 3D points to pixel coordinates before it draws anything. To do this, it draws a line from each point in the scene to your eye and takes the intersection of the lines and the screen rectangle, as in the above picture. So, when OpenGL wants to draw a triangle, it converts the three vertices into pixel coordinates and draws a “2D” triangle using those coordinates.

The user’s “eye” is always at the origin and looking in the negative z direction. Of course, OpenGL doesn’t draw anything that is behind the “eye”. (After all, it isn’t the all-seeing eye of Sauron.)

How far away is the screen rectangle from your eye? Actually, it doesn’t matter. No matter how far away the screen rectangle is, a given 3D point will map to the same pixel coordinates. All that matters is the angle that your eye can see.

Going Through the Source Code

All of this stuff about pixel coordinates is great and all, but as programmers, we want to see some code. Take a look at main.cpp.

The first thing you’ll notice is the license indicating that the code, like all of my code on this site, is completely free. That’s right, F-R-E-E. You can even use it in commercial projects.

The second thing you’ll notice is that it’s heavily commented, so much so that it’s a bit of an eye sore. That’s because this is the first lesson. Other lessons will not be so heavily commented, but they’ll still have comments.

Let’s go through the file and see if we can understand what it’s doing.

#include <stdlib.h> //Needed for "exit" function

//Include OpenGL header files, so that we can use OpenGL
#ifdef __APPLE__

First, we include our header files. Pretty standard stuff for C++. If we’re using a Mac, we want our program to include GLUT/glut.h and OpenGL/OpenGL.h; otherwise, we include GL/glut.h.

using namespace std;

We’ll have this line near the top of main.cpp in all of our programs. It just makes it so that we don’t have to type std:: a lot; for example, so we can use cout instead of std::cout.

//Called when a key is pressed
void handleKeypress(unsigned char key, //The key that was pressed
                    int x, int y) {    //The current mouse coordinates
    switch (key) {
        case 27: //Escape key
            exit(0); //Exit the program

This function handles any keys pressed by the user. For now, all that it does is quit the program when the user presses ESC, by calling exit. The function is passed the x and y coordinates of the mouse, but we don’t need them.

//Initializes 3D rendering
void initRendering() {
    //Makes 3D drawing work when something is in front of something else

The initRendering function initializes our rendering parameters. For now, it doesn’t do much. We’ll pretty much always want to call glEnable(GL_DEPTH_TEST) when we initialize rendering. The call makes sure that an object shows up behind an object in front of it that has already been drawn, which we want to happen.

Note that glEnable, like every OpenGL function, begins with “gl”.

//Called when the window is resized
void handleResize(int w, int h) {
    //Tell OpenGL how to convert from coordinates to pixel values
    glViewport(0, 0, w, h);

    glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective

    //Set the camera perspective
    glLoadIdentity(); //Reset the camera
    gluPerspective(45.0,                  //The camera angle
                   (double)w / (double)h, //The width-to-height ratio
                   1.0,                   //The near z clipping coordinate
                   200.0);                //The far z clipping coordinate

The handleResize function is called whenever the window is resized. w and h are the new width and height of the window. The content of handleResize will be not change much in our other projects, so you don’t have to worry about it too much.

There are a couple of things to notice. When we pass 45.0 to gluPerspective, we’re telling OpenGL the angle that the user’s eye can see. The 1.0 indicates not to draw anything with a z coordinate of greater than -1. This is so that when something is right next to our eye, it doesn’t fill up the whole screen. The 200.0 tells OpenGL not to draw anything with a z coordinate less than -200. We don’t care very much about stuff that’s really far away.

So, why does gluPerspective begin with “glu” instead of “gl”? That’s because technically, it’s a GLU (GL Utility) function. In addition to “gl” and “glu”, some functions we call will begin with “glut” (GL Utility Toolkit). We won’t really worry about the difference among OpenGL, GLU, and GLUT.

//Draws the 3D scene
void drawScene() {
    //Clear information from last draw

The drawScene function is where the 3D drawing actually occurs. First, we call glClear to clear information from the last time we drew. In most every OpenGL program, you’ll want to do this.

    glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
    glLoadIdentity(); //Reset the drawing perspective

For now, we’ll ignore this. It’ll make sense after the next lesson, which covers transformations.

    glBegin(GL_QUADS); //Begin quadrilateral coordinates

    glVertex3f(-0.7f, -1.5f, -5.0f);
    glVertex3f(0.7f, -1.5f, -5.0f);
    glVertex3f(0.4f, -0.5f, -5.0f);
    glVertex3f(-0.4f, -0.5f, -5.0f);

    glEnd(); //End quadrilateral coordinates

Here, we begin the substance of our program. This part draws the trapezoid. To draw a trapezoid, we call glBegin(GL_QUADS) to tell OpenGL that we want to start drawing quadrilaterals. Then, we specify the four 3D coordinates of the vertices of the trapezoid, in order, using calls to glVertex3f. When we call glVertex3f, we are specifying three (that’s where the “3” comes from) float (that’s where the “f” comes from) coordinates. Then, since we’re done drawing quadrilaterals, we callglEnd(). Note that every call to glBegin must have a matching call to glEnd.

All of the “f”‘s after the vertex coordinates force the compiler to treat the numbers as floats. Technically, I don’t think that they’re necessary, but I’m going to be using them everywhere.

    glBegin(GL_TRIANGLES); //Begin triangle coordinates

    glVertex3f(0.5f, 0.5f, -5.0f);
    glVertex3f(1.5f, 0.5f, -5.0f);
    glVertex3f(0.5f, 1.0f, -5.0f);

    glVertex3f(0.5f, 1.0f, -5.0f);
    glVertex3f(1.5f, 0.5f, -5.0f);
    glVertex3f(1.5f, 1.0f, -5.0f);

    glVertex3f(0.5f, 1.0f, -5.0f);
    glVertex3f(1.5f, 1.0f, -5.0f);
    glVertex3f(1.0f, 1.5f, -5.0f);

Now, we draw the pentagon. To draw it, we split it up into three triangles, which is pretty standard for OpenGL. We start by calling glBegin(GL_TRIANGLES) to tell OpenGL that we want to draw triangles. Then, we tell it the coordinates of the vertices of the triangles.

OpenGL automatically puts the coordinates together in groups of three. Each group of three coordinates represents one triangle.

    glVertex3f(-0.5f, 0.5f, -5.0f);
    glVertex3f(-1.0f, 1.5f, -5.0f);
    glVertex3f(-1.5f, 0.5f, -5.0f);

Finally, we draw the triangle. We haven’t called glEnd() to tell OpenGL that we’re done drawing triangles yet, so it knows that we’re still giving it triangle coordinates.

    glEnd(); //End triangle coordinates

Now, we’re done drawing triangles, so we call glEnd().

Note that we could have drawn the above four triangles using four calls to glBegin(GL_TRIANGLES) and four accompanying calls to glEnd(). However, this makes the program slower, and you shouldn’t do it.

There are other things we can pass to glBegin in addition to GL_TRIANGLES and GL_QUADS, but triangles and quadrilaterals are the most common things to draw.

    glutSwapBuffers(); //Send the 3D scene to the screen

This line makes OpenGL actually move the scene to the window. We’ll call it whenever we’re done drawing a scene.

int main(int argc, char** argv) {
    //Initialize GLUT
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(400, 400); //Set the window size

    //Create the window
    glutCreateWindow("Basic Shapes -");
    initRendering(); //Initialize rendering

This is the program’s main function. We start by initializing GLUT. Again, something similar will appear in all of our programs, so you don’t have to worry too much about it. In the call to glutInitWindowSize, we set the window to be 400×400. When we call glutCreateWindow, we tell it what title we want for the window. Then, we call initRendering, the function that we wrote to initialize OpenGL rendering.

    //Set handler functions for drawing, keypresses, and window resizes

Now, we point GLUT to the functions that we wrote to handle keypresses and drawing and resizing the window. One important thing to note: we’re not allowed to draw anything except inside the drawScene function that we explicitly give to GLUT, or inside functions that drawScene calls (or functions that they call, etc.).

    glutMainLoop(); //Start the main loop.  glutMainLoop doesn't return.
    return 0; //This line is never reached

Next, we call glutMainLoop, which tells GLUT to do its thing. This is, we tell GLUT to capture key and mouse input, to draw the scene when it has to by calling our drawScene function, and to do some other stuff.

glutMainLoop, like a defective boomerang, never returns. GLUT just takes care of the rest of our program’s execution. After the call, we have return 0 so that the compiler doesn’t complain about the main function not returning anything, but the program will never get to that line.

And that’s how our first OpenGL program works. You may want to try the exercises to get more familiar with what you just learned.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Extracts from a Personal Diary

dedicated to the life of a silent girl who eventually learnt to open up

Num3ri v 2.0

I miei numeri - seconda versione


Just another site

Algunos Intereses de Abraham Zamudio Chauca

Matematica, Linux , Programacion Serial , Programacion Paralela (CPU - GPU) , Cluster de Computadores , Software Cientifico




A great site

Travel tips

Travel tips

Experience the real life.....!!!

Shurwaat achi honi chahiye ...

Ronzii's Blog

Just your average geek's blog

Karan Jitendra Thakkar

Everything I think. Everything I do. Right here.


News About Tech, Money and Innovation

Chetan Solanki

Helpful to u, if u need it.....


Explorer of Research #HEMBAD


Explorer of Research #HEMBAD


A great site


This is My Space so Dont Mess With IT !!

%d bloggers like this: