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

 } // Loop Until All 256 Are Built

}

KillFont is still the same. We created 256 display lists, so we need to destroy 256 display lists when the program closes.

GLvoid KillFont(GLvoid) // Delete The Font From Memory

{

 glDeleteLists(base,256); // Delete All 256 Display Lists

}

The glPrint() code has only changed a bit. The letters are all stretched on the y axis. Making the letters very tall. I've explained the rest of the code in other tutorials. The stretching is accomplished with the glScalef(x,y,z) command. We leave the ratio at 1.0 on the x axis, we double the size on the y axis (2.0), and we leave it at 1.0 on the z axis.

GLvoid glPrint(GLint x, GLint y, int set, const char *fmt, …) // Where The Printing Happens

{

 char text[1024]; // Holds Our String

 va_list ap; // Pointer To List Of Arguments

 if (fmt == NULL) // If There's No Text

  return; // Do Nothing

 va_start(ap, fmt); // Parses The String For Variables

 vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers

 va_end(ap); // Results Are Stored In Text

 if (set>1) // Did User Choose An Invalid Character Set?

 {

  set=1; // If So, Select Set 1 (Italic)

 }

 glEnable(GL_TEXTURE_2D); // Enable Texture Mapping

 glLoadIdentity(); // Reset The Modelview Matrix

 glTranslated(x,y,0); // Position The Text (0,0 – Top Left)

 glListBase(base-32+(128*set)); // Choose The Font Set (0 or 1)

 glScalef(1.0f,2.0f,1.0f); // Make The Text 2X Taller

 glCallLists(strlen(text),GL_UNSIGNED_BYTE, text); // Write The Text To The Screen

 glDisable(GL_TEXTURE_2D); // Disable Texture Mapping

}

ReSizeGLScene() sets up an ortho view. Nothing really new. 0,1 is the top left of the screen. 639,480 is the bottom right. This gives us exact screen coordinates in 640 x 480 resolution. Notice that we set the value of swidth to equal the windows current width, and we set the value of sheight to equal the windows current height. Whenever the window is resized or moved, sheight and swidth will be updated.

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window

{

 swidth=width; // Set Scissor Width To Window Width

 sheight=height; // Set Scissor Height To Window Height

 if (height==0) // Prevent A Divide By Zero By

 {

  height=1; // Making Height Equal One

 }

 glViewport(0,0,width,height); // Reset The Current Viewport

 glMatrixMode(GL_PROJECTION); // Select The Projection Matrix

 glLoadIdentity(); // Reset The Projection Matrix

 glOrtho(0.0f,640,480,0.0f,-1.0f,1.0f); // Create Ortho 640x480 View (0,0 At Top Left)

 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix

 glLoadIdentity(); // Reset The Modelview Matrix

}

The init code is very minimal. We load our TGA file. Notice that the first parameter passed is &textures[0]. The second parameter is the name of the file we want to load. In this case, we want to load the Font.TGA file. If LoadTGA() returns false for any reason, the if statement will also return false, causing the program to quit with an "initialization failed" message.

If you wanted to load a second texture you could use the following code: if ((!LoadTGA(&textures[0],"image1.tga")) || (!LoadTGA(&textures[1],"image2.tga"))) { }

After we load the TGA (creating our texture), we build our font, set shading to smooth, set the background color to black, enable clearing of the depth buffer, and select our font texture (bind to it).

Lastly we return true so that our program knows that initialization went ok.

int InitGL(GLvoid) // All Setup For OpenGL Goes Here

{

 if (!LoadTGA(&textures[0],"Data/Font.TGA")) // Load The Font Texture

 {

  return false; // If Loading Failed, Return False

 }

 BuildFont(); // Build The Font

 glShadeModel(GL_SMOOTH); // Enable Smooth Shading

 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background

 glClearDepth(1.0f); // Depth Buffer Setup

 glBindTexture(GL_TEXTURE_2D, textures[0].texID); // Select Our Font Texture

 return TRUE; // Initialization Went OK

}

The draw code is completely new :) we start off by creating a variable of type char called token. Token will hold parsed text later on in the code.

We have another variable called cnt. I use this variable both for counting the number of extensions supported, and for positioning the text on the screen. cnt is reset to zero every time we call DrawGLScene.

We clear the screen and depth buffer and then set the color to bright red (full red intensity, 50% green, 50% blue). at 50 on the x axis and 16 on the y axis we write teh word "Renderer". We also write "Vendor" and "Version" at the top of the screen. The reason each word does not start at 50 on the x axis is because I right justify the words (they all line up on the right side).

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing

{

 char *token; // Storage For Our Token

 int cnt=0; // Local Counter Variable

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

 glColor3f(1.0f,0.5f,0.5f); // Set Color To Bright Red

 glPrint(50,16,1,"Renderer"); // Display Renderer

 glPrint(80,48,1,"Vendor"); // Display Vendor Name

 glPrint(66,80,1,"Version"); // Display Version

Now that we have text on the screen, we change the color to orange, and grab the renderer, vendor name and version number from the video card. We do this by passing GL_RENDERER, GL_VENDOR & GL_VERSION to glGetString(). glGetString will return the requested renderer name, vendor name and version number. The information returned will be text so we need to cast the return information from glGetString as char. All this means is that we tell the program we want the information returned to be characters (text). If you don't include the (char *) you will get an error message. We're printing text, so we need text returned. We grab all three pieces of information and write the information we've grabbed to the right of the previous text.

The information we get from glGetString(GL_RENDERER) will be written beside the red text "Renderer", the information we get from glGetString(GL_VENDOR) will be written to the right of "Vendor", etc.

I'd like to explain casting in more detail, but I'm not really sure of a good way to explain it. If anyone has a good explanation, send it in, and I'll modify my explanation.

After we have the renderer information, vendor information and version number written to the screen, we change the color to a bright blue, and write "NeHe Productions" at the bottom of the screen :) Of course you can change this to anything you want.

 glColor3f(1.0f,0.7f,0.4f); // Set Color To Orange

 glPrint(200,16,1,(char *)glGetString(GL_RENDERER)); // Display Renderer