Выбрать главу

A Quick OpenGL Tutorial

Platform: Multi-platform

Welcome to my OpenGL tutorial! Recently, with the appearance of high-performance 3D graphics cards on the PC, 3D applications are no longer delegated to the realm of the expensive custom workstation. For a C programmer, this means more than games – 3D is already being used in hundreds of application areas which previously were somewhat… flat.

The de-facto standard for a 3D api for many years was OpenGL, originally made by SGI. Unfortunetly, when it came time to port OGL over to the PC platform to take advantage of the new accelerated graphics cards, Microsoft was hard at work at it's own 3D standard-Direct3D. The result was that MS dragged its feet somewhat and released a somewhat shoddy software-only port of OpenGL on Windows 95. SGI also released a software-only version which takes advantage of acceleration techniques such as the MMX instruction set, and many card manufactures (such as those that use the 3Dfx chipset) provide their own drivers for interfacing with their boards. Unfortunetly, Microsoft has made it clear by their actions that Direct3D will be the only api they will support for Windows 95 (and the upcoming Windows 98).

So where does that leave us, the development community? Well, you could learn Direct3D…the process of which has several drawbacks: Firstly, Direct3D is by far the most horridly designed 3D api that has ever existed. Also, since it is built on top of DirectDraw, you must also learn that library before you can even begin D3D work. In addition, if you don't know how to interface to COM libraries (which in itself is no joy from C), that's another learning curveball thrown your way. Finally, there is the obvious fact that Direct3D only works for Win95, so cross-platform development is out of the question. If you want the full story on the horrors of Direct3D, you can check out a D3D tutorial at http://www.wksoftware.com/publications/d3dim.html.

Anyway, this tutorial is intended for C (or C++) programmers who have a moderate to strong grasp of the language. There is no 3D experience required to learn OpenGL, although it could help make some of the concepts clearer. One of the nice things about OpenGL is that it's easy to use – the interface is straightforward with no excess baggage. Likewise rather than use COM to provide an object-oriented paradigm in both C and C++, OpenGL is implemented as C functions which can be organized in any manner you see fit. There are good C++ encapsulations of OpenGL availible, but in this tutorial I'm just going over the basics, so I won't hide the interface. Now on that note, lets get started.

I. Introduction To OpenGL

OK, I assume if you're still here then you're hyped up to begin learning OpenGL. First off, you have to get the libraries…

OpenGL should be availible on whatever platform you happen to be on. The libraries and headers for Microsoft's version comes with Visual C++, or you can download them from Microsoft's site. Alternativly, you can hunt around for SGI's drivers at http://www.sgi.com/. If you're running Linux, I'd suggest getting Mesa. It's availible for free at sunsite (ftp://sunsite.unc.edu/pub/packages/development/graphics/mesa/). Whichever OGL library you get, you're also going to need some sort of windowing system to support it. For these examples I'm going to be using the GLUT, or OpenGL Utility Toolkit (ftp://sunsite.unc.edu/pub/packages/development/graphics/glut/). GLUT's main job is to provide a window to draw your OpenGL code into. GLUT is also portable, which means you can compile the same code for both Win95 and X-Windows.

Now that that's out of the way, lets go on to:

/**********************************************************************/

/******************************************/

/* A Very Simple OpenGL Example! */

/******************************************/

/* this code just creates a window and draws a rectangle in it */

#include <windows.h> /* obviously change this to your native library if you're compiling under unix */

#include <gl\gl.h>

#include <gl\glut.h>

void init(void);

void display(void);

int main (int argc, char **argv) {

 glutInit(&argc, argv);

 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

 glutInitWindowSize(250, 250);

 glutInitWindowPosition(100, 100);

 glutCreateWindow("My First OpenGL Application");

 init();

 glutDisplayFunc(display);

 glutMainLoop();

 return 0;

}

void init(void) {

 glClearColor(0.0, 0.0, 0.0, 0.0);

 glColor3f(0.0, 0.0, 1.0);

 glMatrixMode(GL_PROJECTION);

 glLoadIdentity();

 glOrtho(-10.0, 10.0, –10.0, 10.0, –10.0, 10.0);

}

void display(void) {

 glClear(GL_COLOR_BUFFER_BIT);

 glRectf(-5.0, 5.0, 5.0, –5.0);

 glutSwapBuffers();

}

/**********************************************************************/

Lets go through this step by step:

First, I called the glutInit function, which provides general initialization for the GLUT library:

int main (int argc, char **argv) {

 glutInit(&argc, argv);

Next I initialize the display mode:

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

This tells OpenGL that I want a double buffered window, with RGB color.

The next few lines create the window:

glutInitWindowSize(250, 250);

glutInitWindowPosition(100, 100);

glutCreateWindow("My First OpenGL Application");

As you can see, with GLUT this is fairly straightforward.

Now it's time to initialize OpenGL. Here's the code:

void init(void) {

 glClearColor(0.0, 0.0, 0.0, 0.0); /* set the background (clearing) color to RGB(0,0,0) – black */

 glColor3f(0.0, 0.0, 1.0); /* set the foreground color to blue */

 glMatrixMode(GL_PROJECTION); /* Initialize the matrix state */

 glLoadIdentity();

 glOrtho(-10.0, 10.0, –10.0, 10.0, –10.0, 10.0);

}

In OpenGL, matrices are used to manage the view. There are two matrix modes, projection and modelview. Projection is used to set up the viewport and clipping boundry, while modelview is used to rotate, translate and scale objects quickly.

Lets take a look at these two lines:

glLoadIdentity();

glOrtho(-10.0, 10.0, –10.0, 10.0, –10.0, 10.0);

glLoadIdentity() loads the identity matrix into the current matrix state (in this case the projection matrix). You can consider this the resetting matrix…it resets everything back to zero. Next comes the call to glOrtho. This function sets up a clipping volume. You can think of a clipping volume as a box in which your drawing commands are rendered. As the viewer, we are positioned outside the box, looking in the front. What we see is whatever is inside the box, projected onto the flat surface that is the side. Anything outside the box is invisible. The glOrtho function creates an orthographic view-that is, one with no perspective. We'll get to perspective drawing later in the tutorial.

The arguments for glOrtho are as follows:

void glOrtho(double left, double right, double bottom, double top, double near, double far);