原创 2005年04月25日 16:07:00

Environment: VC6

Well, here is good news for all game lovers and beginning game programmers. This article will show you how to create a simple Balloon Show game using OpenGL libraries. The OpenGL libraries can be used with other language platforms, but it is best to use them with the Visual C++ environment because most of the game programmers use VC++ to make their games. This article shows the step by step handling from the beginning till the end.

The first thing you will have to do is build a project in Visual C++. After you have created a new Win32 Application (not a console application) in Visual C++, you will need to link the OpenGL libraries. In Visual C++, go to Project, Settings, and then click on the LINK tab. Under "Object/Library Modules" at the beginning of the line (before kernel32.lib), add OpenGL32.lib GLu32.lib and GLaux.lib. Once you've done this, click OK. You're now ready to write an OpenGL Windows program. Your program should include all these header files:

#include "windows.h"     // Header File For Windows
#include "gl/gl.h"       // Header File For The OpenGL32 Library
#include "gl/glu.h"      // Header File For The GLu32 Library
#include "gl/glaux.h"    // Header File For The GLaux Library

The few variables that we do set up are very important, and will be used in just about every OpenGL program you write using this code. The data types for OpenGL are also defined. For example:


The first line sets up a Rendering Context. Every OpenGL program is linked to a Rendering Context. A Rendering Context is what links OpenGL calls to the Device Context. The OpenGL Rendering Context is defined as hRC. In order for your program to draw to a Window, you need to create a Device Context; this is done in the second line. The Windows Device Context is defined as hDC. The DC connects the Window to the GDI (Graphics Device Interface). The RC connects OpenGL to the DC.

HDC       hDC=NULL;     // Private GDI Device Context
HGLRC     hRC=NULL;     // Permanent Rendering Context
HWND      hWnd=NULL;    // Holds Our Window Handle
HINSTANCE hInstance;    // Holds The Instance Of The Application

The first line below sets up an array, keys[256], that we will use to monitor key presses on the keyboard. There are many ways to watch for key presses on the keyboard, but this is the way I do it. It's reliable, and it can handle more than one key being pressed at a time.

The active variable will be used to tell our program whether or not our Window has been minimized to the taskbar. The variable fullscreen is fairly obvious. If our program is running in fullscreen mode, fullscreen will be TRUE; if our program is running in Windowed mode, fullscreen will be FALSE.

bool keys[256];        // Array Used For The Keyboard Routine
bool active=TRUE;      // Window Active Flag Set To TRUE By Default/
bool fullscreen=TRUE;  // Fullscreen Flag Set To Fullscreen Mode
                       // By Default

In the following line, we define WndProc() so that CreateGLWindow() can make reference to WndProc().


The OpenGL scene will be resized based on the width and height of the window it's being displayed in.

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
  // Resize And Initialize The GL Window
  if (height==0)    // Prevent A Divide By Zero By
  {                 // Making Height Equal One
  glViewport(0, 0, width, height);  // Reset The Current Viewport

The following lines set the screen up for a perspective view. This means that things in the distance get smaller. This creates a realistic looking scene. The perspective is calculated with a 45 degree viewing angle based on the window's width and height. The 0.1f, 100.0f are the starting point and ending point for how deep we can draw into the screen.

glMatrixMode(GL_PROJECTION);   // Select The Projection Matrix
glLoadIdentity();              // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);    // Select The Modelview Matrix
glLoadIdentity();              // Reset The Modelview Matrix

In the next section of code, we do all of the setup for OpenGL. We set what color to clear the screen to, and we turn on the depth buffer, enable smooth shading, and so forth. This routine will not be called until the OpenGL Window has been created.

int InitGL(GLvoid)                      // All Setup For OpenGL
                                        // Goes Here
glShadeModel(GL_SMOOTH);                // Enables Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);   // Black Background
glClearDepth(1.0f);                     // Depth Buffer Setup
glEnable(GL_DEPTH_TEST);                // Enables Depth Testing
glDepthFunc(GL_LEQUAL);                 // The Type Of Depth Test
                                        // To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT,  // Really Nice Perspective
       GL_NICEST);                      // Calculations
return TRUE;                            // Initialization Went OK

Anything you plan to display on the screen will go in this section of code.

int DrawGLScene(GLvoid)    // Here's Where We Do All The Drawing
// Clear The Screen And The Depth Buffer

The next three lines of code position and rotate the texture mapped cube. glTranslatef(0.0f,0.0f,z) moves the cube to the value of z on the z plane (away from and towards the viewer). glRotatef (xrot,1.0f,0.0f,0.0f) uses the variable xrot to rotate the cube on the x axis. glRotatef (yrot,1.0f,0.0f, 0.0f) uses the variable yrot to rotate the cube on the y axis. These things will be covered in detail later.

glTranslatef(0.0f,0.0f,z);         // Translate Into/Out Of The
                                   // Screen By z
glRotatef(xrot,1.0f,0.0f,0.0f);    // Rotate On The X Axis By xrot
glRotatef(yrot,0.0f,1.0f,0.0f);    // Rotate On The Y Axis By yrot

By using the variable filter, we can select any of the three textures we've made.

glBindTexture(GL_TEXTURE_2D, texture[filter]);
// Select A Texture Based On filter

The following lines create a new Quadratic object that maps a given bitmap texture to a sphere. Here we map the texture for making the balloon a sphere shape.

q = gluNewQuadric();                    // Create A New Quadratic
gluQuadricNormals(q, GL_SMOOTH);        // Generate Smooth Normals
                                        // For The Quad
gluQuadricTexture(q, GL_TRUE);          // Enable Texture Coords
                                        // For The Quad
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,    // Set Up Sphere Mapping
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,    // Set Up Sphere Mapping

The following code is to make a cube with given bitmap textures on all sides of the cube—front, back, top, bottom, right, and left. The code for the front side is shown here and the rest is in the source code provided with this article.

glBegin(GL_QUADS);                  // Front Face
glNormal3f( 0.0f, 0.0f, 1.0f);      // Normal Pointing Towards
                                    // Viewer
glTexCoord2f(0.0f, 0.0f);           // Point 1 (Front)
  glVertex3f(-1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f);           // Point 2 (Front)
  glVertex3f( 1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f);           // Point 3 (Front)
  glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 1.0f);
  glVertex3f(-1.0f,  1.0f,  1.0f);  // Point 4 (Front)

glLoadIdentity();    // Reset The Current Modelview Matrix
return TRUE;         // Everything Went OK

The following function code destroys the OpenGL window. The first thing we do in KillGLWindow() is check to see whether we are in fullscreen mode. If we are, we'll switch back to the desktop.

GLvoid KillGLWindow(GLvoid)

The following function creates a OpenGL window and here you can set the size, style, and other attributes of the window.

BOOL CreateGLWindow(char* title, int width, int height,
                    int bits, bool fullscreenflag)

Texture Binding

GLuint texture[3] creates storage space for the three different textures. The textures will be stored at texture[0], texture[1], and texture[2].

GLuint texture[3];    // Storage for 3 textures

AUX_RGBImageRec *LoadBMP(char *Filename)

Now we load in a bitmap. The above function codes the loading, and building texture maps from bitmap images. The section of code that loads the bitmap (calling the code above) and converts it into three textures. A variable Status is used to keep track of whether or not the texture was loaded and created. The variable for storing the image is AUX_RGBImageRec. This is created in the function int LoadGLTextures().

Creating Motion Effects

Now we're going to set up five variables that will control the angle on the x axis (xrot), the angle on the y axis (yrot), the speed the crate is spinning at on the x axis (xspeed), and the speed the crate is spinning at on the y axis (yspeed). We'll also create a variable called z that will control how deep into the screen (on the z axis) the balloon is or its zoom is.

GLfloat xrot;           // X Rotation
GLfloat yrot;           // Y Rotation
GLfloat xspeed;         // X Rotation Speed
GLfloat yspeed;         // Y Rotation Speed
GLfloat z=-5.0f;        // Depth (zoom) into the Screen
GLfloat height=2.0f;    // Height Of Balloon From Floor

Creating Lighting Effects

We create a variable called light to keep track of whether the lighting is on or off.

BOOL light;    // Lighting ON / OFF

The first type of light is called ambient light. Ambient light is light that doesn't come from any particular direction. All the objects in your scene will be lit up by the ambient light. The second type of light is called diffuse light. Diffuse light is created by your light source and is reflected off the surface of an object in your scene. Any surface of an object that the light hits directly will be very bright, and areas the light barely gets to will be darker. This creates a nice shading effect on the sides of our crate and the balloon.

GLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };
  // Ambient Light Values ( NEW )
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
  / Diffuse Light Values ( NEW )/

This tells OpenGL the designated coordinates are the position of the light source.

GLfloat LightPosition[]= { 0.0f, 0.0f,    // Light Position ( NEW )
                           2.0f, 1.0f };

The variables lp and fp are used to store whether or not the 'L' or 'F' key has been pressed.

BOOL lp;    // L Pressed?
BOOL fp;    // F Pressed?

Creating Filter Effects

GLuint filter;    // Which Filter To Use

The filter variable above keeps track of which texture to display. The first texture (texture 0) is made using gl_nearest (no smoothing). The second texture (texture 1) uses gl_linear filtering, which smooths the image out quite a bit. The third texture (texture 2) uses mipmapped textures, creating a very nice looking texture. The variable filter will equal 0, 1, or 2, depending on the texture we want to use. We start off with the first texture.

You'll notice we're using GL_NEAREST for both the MIN and MAG. You can mix GL_NEAREST with GL_LINEAR, and the texture will look a bit better, but we're interested in speed, so we'll use low quality for both. The MIN_FILTER is the filter used when an image is drawn smaller than the original texture size. The MAG_FILTER is used when the image is bigger than the original texture size.

// Create Nearest Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX,
             TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,

In using linear filtered texture maps, they require a hefty amount of processing power, but they look really nice. The first type of texture we're going to create in this tutorial uses GL_NEAREST. Basically, this type of texture has no filtering at all. It takes very little processing power, and it looks really bad. If you've ever played a game where the textures look all blocky, it's probably using this type of texture.

// Create Linear Filtered Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX,
             TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,

When you tell OpenGL to build a mipmapped texture, OpenGL tries to build different-sized, high quality textures. When you draw a mipmapped texture to the screen, OpenGL will select the BEST looking texture from the ones it built (texture with the most detail) and draw it to the screen instead of resizing the original image (which causes detail loss).

// Create MipMapped Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);

The following line builds the mipmapped texture. We're creating a 2D texture using three colors (red, maroon, amd blue). TextureImage[0]->sizeX is the bitmap's width, TextureImage[0]->sizeY is the bitmap's height, GL_RGB means we're using Red, Maroon, amd Blue colors in that order. GL_UNSIGNED_BYTE means the data that makes the texture is made up of bytes, and TextureImage[0]->data points to the bitmap data that we're building the texture from.

gluBuild2DMipmaps(GL_TEXTURE_2D, 3,      //( NEW )
                  TextureImage[0]->sizeY, GL_RGB,
                  GL_UNSIGNED_BYTE, TextureImage[0]->data);

Creating Fogging Effects

We'll start by setting up all our variables needed to hold the information for fog. The variable fogMode will be used to hold three types of fog: GL_EXP, GL_EXP2, and GL_LINEAR. I will explain the differences among these three later on. The variables will start at the beginning of the code, after the line GLuint texture[3]. The variable fogfilter will be used to keep track of which fog type we will be using. The variable fogColor will hold the color we want the fog to be. I have also added the boolean variable gp at the top of the code so we can tell whether the 'g' key is being pressed.

bool   gp;                           // G Pressed? ( New )
GLuint fogMode[]= { GL_EXP, GL_EXP2,
                    GL_LINEAR };     // Storage For Three Types
                                     // Of Fog
GLuint fogfilter= 0;                 // Which Fog To Use
GLfloat fogColor[4]= {0.5f, 0.5f,    // Fog Color
                      0.5f, 1.0f};

The DrawGLScene() function has the following code to enable fog effects:

glClearColor(0.5f,0.5f,0.5f,1.0f);          // We'll Clear To The
                                            // Color Of The Fog
                                            // ( Modified )

glFogi(GL_FOG_MODE, fogMode[fogfilter]);    // Fog Mode
glFogfv(GL_FOG_COLOR, fogColor);            // Set Fog Color
glFogf(GL_FOG_DENSITY, 0.35f);              // How Dense Will The
                                            // Fog Be
glHint(GL_FOG_HINT, GL_DONT_CARE);          // Fog Hint Value
glFogf(GL_FOG_START, 1.0f);                 // Fog Start Depth
glFogf(GL_FOG_END, 5.0f);                   // Fog End Depth

glEnable(GL_FOG);                           // Enables GL_FOG

The above line, glEnable(GL_FOG);, is pretty much self explanatory. It basically initializes the fog. The line glFogi(GL_FOG_MODE, fogMode [fogfilter] ); establishes the fog filter mode. Now, earlier we declared the array fogMode. It held GL_EXP, GL_EXP2, and GL_LINEAR. Here is when these variables come into play. Let me explain each one:

  • GL_EXP: Basic rendered fog that fogs out all of the screen. It doesn't give much of a fog effect, but gets the job done on older PCs.
  • GL_EXP2: Is the next step up from GL_EXP. This will fog out all of the screen; however, it will give more depth to the scene.
  • GL_LINEAR: This is the best fog rendering mode. Objects fade in and out of the fog much better.
  • glFogfv(GL_FOG_COLOR, fogcolor): Sets the color of the fog. The line glFogf(GL_FOG_DENSITY, 0.35f); establishes how dense the fog will be. Increase the number and the fog becomes more dense; decrease it and it becomes less dense.
  • glHint (GL_FOG_HINT, GL_DONT_CARE): Establishes the hint. I used GL_DONT_CARE, because I didn't care about the hint value. Hint value can be one of the following types:
    • gl_dont_care: Lets OpenGL choose the kind of fog (per vertex of per pixel) and an unknown formula.
    • gl_nicest: Makes the fog per pixel (looks good)
    • glfastest: Makes the fog per vertex (faster, but not as nice)

About the Author

Fatima Ahmed is in B.S. (Computer Science) Karachi University, a well-known university in Pakistan. Her interests are in writing technical articles for magazines and e-zines, surfing the net, making projects, and doing programming in different languages. Her articles can be found on this and other Web sites. You can contact her at: or


NeHe's game programming Tutorials.


Download source - 87 Kb

OpenGL 入门基础知识

环境      Android Studio      使用JAVA 学习 OpenGLES  参考书籍  《OpenGL es 2.0 上卷》 ...
  • talent_jian
  • talent_jian
  • 2016年10月16日 22:52
  • 506

渲染世界的Opengl<1> Opengl基础知识整理

  • memories_sunset
  • memories_sunset
  • 2016年07月25日 20:21
  • 739

OpenGL学习笔记(一) 纹理基础知识

一篇纹理的详细介绍文章 OpenGL函数库文档
  • lixiang996
  • lixiang996
  • 2011年10月10日 23:44
  • 5704


  • candycat1992
  • candycat1992
  • 2014年09月30日 12:26
  • 15732

整理 qt opengl,自己的基础框架 —— 绘制一个彩色三角形

  • imxiangzi
  • imxiangzi
  • 2016年09月24日 14:31
  • 764


OpenGL 数据类型 首先我们要讨论的是OpenGL的数据类型。因为OpenGL是一个跨平台的API,数据类型的大小会随使用的编程语言以及处理器(64位,32位,16位)等的不同而不同,所以O...
  • sunyong445
  • sunyong445
  • 2013年11月13日 16:44
  • 557


一、OpenGL数据类型   与C语言相对应,OpenGL中也有整数、字节、浮点数等数据类型,为了说明两者的对应关系,下表将OpenGL的数据类型与相应的C类型进行了对比: 前...
  • llq108
  • llq108
  • 2013年04月02日 19:48
  • 553


转载自 你需要明白OpenGL如何绘制并决定我们看到的东西。 相对于...
  • u010464297
  • u010464297
  • 2015年10月01日 21:35
  • 318

OpenGL ES 基础概念介绍

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。 首先,光栅化(R...
  • zhenyu5211314
  • zhenyu5211314
  • 2016年06月29日 14:23
  • 1044

Qt OpenGL渲染文字

看本文章的人我相信都不需要我介绍Qt和OpenGL了。文字的绘制一直都是3D开发的一个难题,本文将介绍一种非常简单,效率也还可以的方法来渲染文字到OpenGL。 先讲原理,Qt的QPainter拥有将...
  • xinxinqqt
  • xinxinqqt
  • 2016年12月23日 20:31
  • 1159