OpenGL Programming/Basics/Rectangles

From Wikibooks, open books for an open world
Jump to: navigation, search

Drawing Rectangles[edit]

Recall from the previous chapter our basic structure for OpenGL/GLUT applications.

#ifndef WIN32 //if using windows then do windows specific stuff.
#define WIN32_LEAN_AND_MEAN //remove MFC overhead from windows.h which can cause slowness
#define WIN32_EXTRA_LEAN

#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <conio.h>//needed for getch

void setup() { /* empty function  nothing to setup yet */ }
void display() { /* empty function   required as of glut 3.0 */ }

int main(int argc, char *argv[])
{
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
       glutInitWindowSize(800,600);
       glutCreateWindow("Hello World");

       setup();
       glutDisplayFunc(display);

       glutMainLoop();

       getch();//pause here to see results or lack there of
       return 0;
}

We're now going to add some things to the setup() and display() functions so we can draw a rectangle.

Changing the Background Colour[edit]

Let's add a line to our setup function:

void setup() {
       glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}

Calling glClearColor() with these arguments will change the background color to white. For now, we're going to leave this line as is without explanation. We'll return to what the 1.0s mean later.

Preparing to Draw[edit]

To allow us to draw, GLUT needs to clear the screen every time we work. This is accomplished through two functions, one at the beginning and one at the end of our display function:

void display() {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       /* drawing commands would go here, if we had any yet... */
       glutSwapBuffers();
}

By using glClear(), we give ourselves a clean slate to work on; everything that was in our buffer (the place in memory where we store the rendering image) before is gone. We're now using a new buffer, so at the end of the function, we need to switch that buffer into our window. In GLUT, this is accomplished through calling glutSwapBuffers().

Don't worry if you don't fully understand why these two functions exist just yet. You'll have time to learn.

Okay, NOW can I draw?[edit]

Let's add a function to display that will give us a simple rectangle:

void display() {
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glColor3f(0.0f, 0.0f, 0.0f);
       glRectf(-0.75f,0.75f, 0.75f, -0.75f);
       glutSwapBuffers();
}

Again, ignore the arguments to glColor3f(). Just trust us for now that this will make our rectangle black, so we can see it against the white background. Then we actually draw the rectangle using the function glRectf(). We pass in as parameters to glRectf() two sets of numbers: the x and y coordinates for one vertex of the rectangle you want to draw, and the x and y coordinates for the opposite vertex. An important thing to note is that these x and y coordinates are not given in pixels, but rather in viewport coordinates.

The Viewport[edit]

You'll notice, if you compile and run the program using the display function above and then resize the window, that your rectangle will grow and shrink as your window does. In this example, the rectangle will take up exactly 75% of the width and 75% of the height of the window. This is because we haven't set our viewport.

The viewport defines how coordinates are mapped from OpenGL space, which uses floating point numbers, to the window space which obviously uses pixels. By default, the viewport assumes that the top left is (-1, 1), the bottom left is (-1, -1), the top right is (1, 1) and the bottom right is (1, -1), regardless of the window position.