CS 5721 - Computer Graphics

Lab 1: Opening Windows and Drawing Lines with OpenGL

Description

In this lab, you will learn the basics about OpenGL and programming with OpenGL. The OpenGL labs will use a cross-platform windowing utility called GLUT (OpenGL Utility Toolkit - http://www.opengl.org/resources/libraries/glut.html). The nice thing about GLUT is that the same code works on Linux, OS X, and Windows-based platforms (generally without modifications).

Step 1: The Skeleton for GLUT-based OpenGL programs

The skeleton for creating OpenGL programs using GLUT is fairly simple. The base code can be downloaded using the following links:

opengl_sample (ZIP, TGZ)

For this first step, grab the ZIP file above and get the MS Windows development environment setup so that you can compile and run the sample code. Instructions for compiling can be found at the top of the main.cpp file. For our labs, I suggest using the Windows environment since we will have direct access to OpenGL-based hardware on the MWAH 177 lab's machines.

Compile and run the sample program. You should see a blank, dark-grey screen.

Step 2: Comments about OpenGL

When you program OpenGL, you need to think about the process of writing your programs a little differently from the way you might write a sequentially executed C/C++ program. By this, I mean that when you program OpenGL, what you are really programming is the graphics hardware on the PC. This may be surprising to you, but when you write OpenGL, you really are writing code for at least two processors: the CPU(s) and the GPU(s). GPU stands for Graphics Processing Unit. So, the commands you use to describe your models, determine the color of vertices, and describe triangles all change the the state of the hardware on your graphics card getting it ready to render and process your 2D or 3D scene. Once you've described your scene, you let OpenGL know that you're ready for it to display the rendered information to the screen. All functions that are prefixed with "gl" are functions that are a part of the OpenGL API. Functions prefixed with "glut" are part of the GLUT API.

In the sample I provided, the function that you will be most interested in for the first few labs is the function

void display(void)

This function does several things that influence the state of the graphics hardware. First, it sets the clear color of the framebuffer and clears it to that color:

glClearColor(0.2, 0.2, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

The framebuffer is what OpenGL renders your scene to before it displays it on the monitor. OpenGL actually maintains 2 framebuffers. One framebuffer is used to display the contents to the screen (front buffer), while the second framebuffer is used to prepare the next frame to display to the monitor (back buffer). This swap of the framebuffers is called double buffering and is what allows things drawn on the screen to appear very smooth.

The next operations

int width = glutGet(GLUT_WINDOW_WIDTH);
int height = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,width,0,height,-1,1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);

change the way in which OpenGL sets up the screen. We will focus on these commands in future labs, but basically, these commands make the screen act like your FrameBuffer class from previous assignment.

The final command

glutSwapBuffers();

is the function that tells OpenGL and the underlying windowing system to swap the front and back framebuffer. The commands you issue to clear the screen or draw objects such as lines write data into the back buffer, while the front buffer is displayed on your screen. The swap buffer commands flips these buffers. This operation is very fast as it only swaps the pointer to the framebuffer so that the scene just now described and rendered to the back framebuffer can become the front framebuffer and thus, be displayed on the screen.

For this lab, you will primarily be adding code between the glDisable and glutSwapBuffers function calls.

Step 3: Changing the Clear color

Change the clear color to different colors and see what happens. The values must be in the range [0, 1]. The arguments specify the red, green, blue, and alpha values for the background. For now, leave alpha at 1.0.

Step 4: Drawing Lines

OpenGL is capable of rendering four types of primitives: points, lines, triangles, and quadrilaterals. When you specify the primitive you want to render, you must also specify the vertices (and attributes such as color) that go along with the primitive.

This is done using the functions, glColor3f, glBegin, glEnd, and glVertex2f.

Each vertex you specify can have it's own color, much like your parametric lines. The glColor3f function must be called prior to the vertex you want to associate the color with. Think of this as changing the current state of OpenGL. If you call glColor3f(1.0, 0.0, 0.0), you will set the current graphics color state to red. Any vertices defined thereafter will have the color red associated with them. If you prefer to use int or short values for your colors, you can alternatively use the functions glColor3i or glColor3s to specify colors in the range [0,255].

The functions glBegin and glEnd delineate a primitive so vertices and colors associated with a particular primitive (in this case, a line) must be called after glBegin and before glEnd.

For drawing lines, glBegin takes one of the following arguments: GL_LINES, GL_LINE_STRIP, or GL_LINE_LOOP, which change the way vertices are interpreted. For creating sets of disconnected line segments, use GL_LINES, which interprets pairs of vertices as single line segments. GL_LINE_STRIP creates a series of connected line segments using the specified vertices. GL_LINE_LOOP creates a closed series of connected line segments between the frist and last vertices.

So, as a complete example, here is a code snippet that will create two red lines:

glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(10, 10); // first line
glVertex2f(50, 50);
glVertex2f(10,120); // second line
glVertex2f(120,10);
glEnd();

Try the code above and spend the rest of the lab time experimenting with line drawing and OpenGL. Create images with different sets of lines, with different colors. Experiment with the different arguments to glBegin and see how you can specify different types of lines. Also experiment with creating windows of different sizes to get used to the GLUT interface a bit. Notice that your programs will quit when you hit the Escape key due to the keyboard callback function.

When you've created something, show the TA so he can record your progress.