Inno3D Home Page Inno3D Home Page

FAQ News Search Archive Forum Articles Tweaks Technology Files Prices SETI
Visit NVIDIA's home page.
Favorite Pics
Click to Enlarge
Articles/Reviews
OCZ Tech Titan 3
Absolute MORPHEUS
1.0GHz Pentium III
eVGA MX Shootout
nForce Preview
AMD AXIA CPU
VisionTek GeForce3
2001 Spring Lineup
GeForce3 Preview
eVGA TwinView Plus
VisionTek GF2 Ultra
OCZ GeForce2 Pro
Winfast GeForce2 MX
GeForce2 vs Quake3
Linksys Cable Router
GF2 FSAA Shootout
GeForce2 MX Preview
Benchmarking Guide
Quake 3 Tune-Up
Power DVD Review
Live! Experiences
Sponsors
Memory from Crucial.com


FastCounter by bCentral

 Visitors Are Online
Powered by Perlonline.com
Drivers/FAQ
NVIDIA
3D Chipset
Gamers Ammo
Reactor Critical
GeForce FAQ
Associates
Dayton's Misc.
G-Force X Sweden
Maximum Reboot
Media Xplosion
NVchips-fr
nV Italia
Riva Station
3D GPU
nV News Home Page

OpenGL Programming - Introduction

By: Mike Chambers - March 20, 2001

Introduction

You can't teach and old dog new tricks is how the saying goes. I've been making a decent living programming computers for the past 15 years spending the early part of my career in Fortran and then moving on to COBOL. I've also worked with a few other forth generation business-related languages as well.

But alas, my job has turned into a semi-technical one as I've taken on the task of developing functional specifications. Basically, a functional specification is documentation used by programmers to add functionality to a computer system. In this case its an all-encompassing enterprise system known as *cough* SAP *cough*.

I've often said that if I could start my career all over, I would become proficient with C/C++ and then explore the mysterious world of real-time 3D graphics using OpenGL. Therefore, I am officially documenting this event as a mid-life crisis, and the desire to maintain geek status.

OpenGL.org

To develop a better understanding of NVIDIA based graphics processors, I figure dabbling around in OpenGL will shed some light and broaden my horizon in the area of 3D graphics. The word dabble was purposely used since it's not my intent to develop something like an OpenGL based graphics engine. I'd probably have better odds at winning the Virginia lottery. Instead, I am going to proceed with caution and plan on documenting and conveying my learning experiences through a series of carefully crafted articles.

What Is OpenGL?

OpenGL is a graphics application programming interface (API) which was originally developed by Silicon Graphics. OpenGL is not in itself a programming laguage, like C++, but functions as an API which can be used as a software development tool for graphics applications. The term Open is significant in that OpenGL is operating system independent. GL refers to graphics language.

OpenGL also contains a standard library referred to as the OpenGL Utilites (GLU). GLU contains routines for setting up viewing projection matrices and describing complex objects with line and polygon approximations.

OpenGL standards are governed by an independent consortium which is referred to as the OpenGL Architecture Review Board. NVIDIA is a member of this board and continues to create a number of extensions to OpenGL in order to expose the API to new hardware features of graphics processors such as their GeForce.

NVIDIA Detonator Drivers

To ensure that calls to OpenGL work as expected, NVIDIA provides an OpenGL driver for the Windows, Linux, and the Macintosh operating systems. In Windows, the driver is referred to as an ICD (Installable Client driver), on Linux it's a DSO (Dynamic Shared Object - basically a DLL), and on the Macintosh it's a GLI driver which is roughly equivalent to a Windows ICD.

For example, when OpenGL services are requested under the Windows operating system (OpenGL32.dll), NVIDIA's OpenGL driver (Nvopengl.dll) assumes control and issues the appropriate instructions for processing.

This brief introduction has only touched on the surface of OpenGL. Additional information regarding OpenGL can be found in SGI's OpenGL Frequently Asked Questions.

Getting Started

Although there are a variety of programming lanuguages which can call OpenGL, most of the information I gathered on the Internet was C/C++ centric. I settled on version 6.0 of Microsoft's Visual C++ and purchased the standard edition for $99 at CompUSA. The package includes a CD with a wealth information from Microsoft's Developer Network and an Introduction to Microsoft Visual C++ 6.0 Standard Edition by Ivor Horton.

Since I'll initially be spending most of the time learning OpenGL, a good set of reference books sounded like a good idea. The OpenGL 1.2 Programming Guide, Third Edition: The Official Guide to Learning OpenGL, Version 1.2 by Mason Woo and the OpenGL SuperBible, Second Edition by Richard S. Wright come highly recommended.

OpenGL 1.2 Programming Guide, Third Edition: The Official Guide to Learning OpenGL, Version 1.2 OpenGL SuperBible, Second Edition

I purchased the OpenGL SuperBible at Barnes and Noble for $44.00 and found the first edition of the OpenGL Version Programming Guide, also referred to as the Red Book, online. The second edition of the Red Book can be viewed at GameDev.net which is in Adobe Acrobat format (7.8MB).

Other web sites that I frequently visited during my early investigation into OpenGL included:

This page contains a plethora of links that will keep one occupied for quite some time as well.

A GLUT-ton For Punishment?

It didn't take long to realize that programming in OpenGL is not a trivial task. But I'm up for the challenge (or at least I think I am). I don't plan on spending much time in C++ initially since most of the samples in the OpenGL SuperBible are based on using the OpenGL Utility Toolkit (GLUT).

As I previously mentioned, OpenGL is platform independent and doesn't contain features such as managing windows or querying input devices. GLUT is a library that works in conjunction with OpenGL and provides an interface to operating system services, such as window management, menus, and input devices. GLUT was originally developed by NVIDIA's Mark Kilgard and ported to Win32 by Nate Robbins.

The GLUT distribution includes source code, along with sample programs, which can be compiled with C++. Precompiled Win32 DLL's, along with library and header files, can also be downloaded. Either distribution contains everything you need to get started programming with GLUT.

Laying The Smack, uhh... Code, Down

We'll begin our look at the features of OpenGL by going over a simple program. While this program won't knock your socks off, it does cover some of the basics.

In the unfortunate event that you don't get anything out of this lesson, you'll probably remember that lines which contain // are program comments and are ignored by the C++ compiler.

Rectangle.c Source Code

 // Program: Rectangle.c
 // Purpose: Draw a 3D rectangle using GLUT interface
 // Author:  Mike Chambers - March 18, 2001

 #include <gl/glut.h>

 // Function to display output

 void RenderScene(void)
   	 
	 {

  	 // Clear color buffer
	 glClear(GL_COLOR_BUFFER_BIT);
 
	 // Set drawing color to green (RGB)
	 glColor3f(0.0f, 1.0f, 0.0f);

	 // Draw rectangle
	 glRectf(50.0f, 150.0f, 150.0f, 50.0f);

	 // Flush drawing commands
	 glFlush();

	 }

 // Called by GLUT when the window is initially opened or resized

 void OpenWindow(GLsizei w, GLsizei h)

	 {
			
	 // Set viewport to window dimensions
	glViewport(0, 0, w, h);

	 // Reset coordinate system
	 glMatrixMode(GL_PROJECTION);
	 glLoadIdentity();
	 gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);

	 }

 // Initialize the rendering state

 void Initialize(void)

	 {

	 // Set clear color to black
	 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	 }

 // Main program entry point

 void main(void)

	 {

	 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

	 glutInitWindowPosition(200, 200);
	 glutInitWindowSize(300, 300);

	 glutCreateWindow("nV News - Rectangle");	

	 glutDisplayFunc(RenderScene);
	 glutReshapeFunc(OpenWindow);

	 Initialize();

	 glutMainLoop();

	 }

Sure looks like Greek to me!

Deciphering The Program

Hey, it's not that bad. We just need to break down the program in small pieces to figure out what's going on. But in order to keep this introduction brief, certain concepts such as viewports, won't be discussed.

#include

First off is the include command which lets C++ know that this program will be using OpenGL and GLUT. The GLUT include is the only include that's needed for this example since it contains includes to the standard Windows (windows.h) and OpenGL libraries (gl.h and glu.h).

RenderScene - glClear()

The next series of statements are part of a user named subroutine, or function, called RenderScene. This subroutine contains OpenGL commands, or commands that begin with gl as opposed to glu or glut.

OpenGL contains a variety of buffers (color, depth, stencil, and accumulation) which are areas in memory used to save data. Prior to rendering a scene, it's a good idea to clear, or initilaize, the appropriate buffers. In our example, the color buffer is cleared since it's the buffer normally used to draw with.

Clearing a color buffer can be a relatively expensive operation as close to two million pixel addresses require initialization at a resolution of 1600x1200. In some cases, multiple buffers can be initialized simultaneously through hardware. Game engines such as Quake will only clear the depth buffer, since there's no point in clearing the color buffer as every pixel in each frame will always be used.

RenderScene - glColor3f()

The primary method of generating color on a monitor in OpenGL is with the RGB, or RBGA mode, which is set using the glutInitDisplayMode() command. Each pixel, which is the smallest visible element the display hardware can put on the screen, can emit different amounts of red, green, and blue light. These colors are referred to as the R, G, and B values. A forth value, which is used for blending colors, is called the alpha value.

RGB Color Mode

RGB Color Mode

The R, G, and B values are floating point numbers which range from 0.0 (none) to 1.0 (full intensity). For example, when R = 0.0, G = 0.0, and B = 1.0 the brightest possible blue is displayed. If R, G, and B are all 0.0, the pixel is black and if all are 1.0, the pixel is drawn in the brightest possible white.

In theory, OpenGL can support an infinite range of colors and is limited by the capability of the display hardware (which is normally 16,777,216 colors, or 256 red x 256 green x 256 blue).

The glColor3f() function uses floating point values to determine the color and defaults to an alpha value of 1.0. If an alpha value other than 1.0 is required, then a call to glColor4f() is necessary.

RenderScene - glRectf()

Models, or objects, in OpenGL are constructed with geometric primitives which consist of points, line segments, and polygons. The process of generating the images corresponding to these models is referred to as rendering.

OpenGL Geometric Primitives

OpenGL Geometric Primitives

Models are defined using vertex data which represents a single point that marks the endpoint of a line or the corner of a polygon. By definition, a vertex is where two edges meet.

Since rectangles are frequently used in OpenGL, a command to easily generate them has been furnished as part of the OpenGL library. The next step in the sample program calls for a rectangle to be generated based on the x and y coordinates that have been furnished to the glRectf() function:

glRectf(50.0f, 150.0f, 150.0f, 50.0f);

The first two coordinates (x1, y1) specify one vertex of the rectangle (upper-left corner) and the second two (x2, y2) specify the opposite vertex of the rectangle (lower-right corner). In this example, the depth, or z-value, of the rectangle defaults to 0.0.

X, Y, Z Coordinate System

X, Y, Z Coordinate System

The same rectangle could also have been created using the polygon geometric primitive based on the follow vertex commands:

glBegin(GL_POLYGON); 
     glVertex2f(50.0f, 150.0f);   // x1, y1 - top-left corner
     glVertex2f(150.0f, 150.0f);  // x2, y1 - top-right corner
     glVertex2f(150.0f, 50.0f);   // x2, y2 - bottom-right corner
     glVertex2f(50.0f, 50.0f);    // x1, y2 - bottom-left corner
glEnd( );

An important concept to remember is that a point is a location in space, and is described by a coordinate in a coordinate system. We typically use the Cartesian coordinate system to describe points in three dimensions by measuring positively or negatively along the X, Y, and Z axes. The point located at (0,0,0) is called the origin of the coordinate system.

RenderScene - glFlush()

The last command in the RenderScene subroutine is a call to glFlush(). This will ensure that the drawing commands are actually executed as opposed to being stored in a buffer awaiting additional OpenGL commands.

OpenWindow

I will be discussing the commands that appear in this subroutine in a follow-up article. For now just remember that this subroutine is called when a window initially appears, is moved, or resized, courtesy of the glutReshapeFunc() command.

Initialize - glClearColor()

The Initialize subroutine specifies the red, green, blue, and alpha values used to clear the color buffer. In our example, the color buffer is set to black. The color buffer remains black until it's changed via a subsequent call to glClearColor() is made.

main

The main part of the program is contained in the routine named main. The order of events takes place as follows:

  • Initialize the color buffer (OpenGL)
  • Select a display mode (GLUT)
  • Open a window (GLUT)
  • Render a rectangle (OpenGL)

You may have noticed that initializing the color buffer, via the call to the Initialize subroutine, was executed first although the command appears towards the end of the program. This is due to the fact that GLUT commands are not executed until the glutMainLoop() command appears.

Although we've selected a single buffer via the GLUT_SINGLE parameter in the glutInitDisplayMode() function, the majority of OpenGL applications use double buffering.

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

When double buffering is enabled, one buffer is displayed while the second buffer is being drawn. When the drawing of a frame is complete, the two buffers are swapped, so the one that was being viewed is now used for drawing, and vice versa. Double buffering is useful in providing smooth animation between frames.

Wrapping It Up

Like I said before this program may not be impressive, but you've got to crawl before you can walk right? The following screen shot shows the results of the program which is the window with the black background containing a green rectangle. I left the Visual C++ user interface up in case you're interested in taking a peak at it.

Program Results

Click to Enlarge - 60K

If you think of the enhancements that can be made to this program, such as transformation (rotation, movement) or adding a texture or light source, there's certainly much more information to learn.

Which brings me to the methodology I used before ever laying down the first C++ code. I spent a great deal of time gathering information from multiple sources on the commands that would be used in the program. I read and re-read information until I thouroughly understood the purpose of each OpenGL command being used. By doing so, I developed an understanding of what took place during program execution.

The executable for this example can be downloaded here (17K). It also requires version 3.7.3 of glut32.dll (219K) which may already be in your windows/system directory.

 
Last Updated on March 20, 2001

All trademarks used are properties of their respective owners.