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

After we have drawn the current count (cnt) to the screen, we change the color to yellow, move 50 pixels to the right on the x axis, and we write the text stored in the variable token to the screen.

Using our example above, the first line of text displayed on the screen should look like this:

1 GL_ARB_multitexture

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

  glPrint(0,96+(cnt*32)-scroll,0,"%i",cnt); // Print Current Extension Number

After we have drawn the current count to the screen, we change the color to yellow, move 50 pixels to the right on the x axis, and we write the text stored in the variable token to the screen.

Using our example above, the first line of text displayed on the screen should look like this:

1   GL_ARB_multitexture

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

  glPrint(50,96+(cnt*32)-scroll,0,token); // Print The Current Token (Parsed Extension Name)

After we have displayed the value of token on the screen, we need to check through the variable text to see if any more extensions are supported. Instead of using token=strtok(text," ") like we did above, we replace text with NULL. This tells the command strtok to search from the last marker to the NEXT space in the string of text (text).

In our example above ("GL_ARB_multitexture marker GL_EXT_abgr GL_EXT_bgra") there will now be a marker after the text "GL_ARB_multitexture". The line below will start search FROM the marker to the next space. Everything from the marker to the next space will be stored in token. token should end up being "GL_EXT_abgr", and text will end up being "GL_ARB_multitexture marker GL_EXT_abgr marker GL_EXT_bgra".

Once strtok() has run out of text to store in token, token will become NULL and the loop will stop.

  token=strtok(NULL," "); // Search For The Next Token

 }

After all of the extensions have been parsed from the variable text we can disable scissor testing, and free the variable text. This releases the ram we were using to hold the information we got from glGetString(GL_EXTENSIONS).

The next time DrawGLScene() is called, new memory will be allocated. A fresh copy of the information returned by glGetStrings(GL_EXTENSIONS) will be copied into the variable text and the entire process will start over.

 glDisable(GL_SCISSOR_TEST); // Disable Scissor Testing

 free (text); // Free Allocated Memory

The first line below isn't necessary, but I thought it might be a good idea to talk about it, just so everyone knows that it exists. The command glFlush() basically tells OpenGL to finish up what it's doing. If you ever notice flickering in your program (quads disappearing, etc). Try adding the flush command to the end of DrawGLScene. It flushes out the rendering pipeline. You may notice flickering if you're program doesn't have enough time to finish rendering the scene.

Last thing we do is return true to show that everything went ok.

 glFlush(); // Flush The Rendering Pipeline

 return TRUE; // Everything Went OK

}

The only thing to note in KillGLWindow() is that I have added KillFont() at the end. That way whenever the window is killed, the font is also killed.

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window

{

 if (fullscreen) // Are We In Fullscreen Mode?

 {

  ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop

  ShowCursor(TRUE); // Show Mouse Pointer

 }

 if (hRC) // Do We Have A Rendering Context?

 {

  if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?

  {

   MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  }

  if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?

  {

   MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  }

  hRC=NULL; // Set RC To NULL

 }

 if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC

 {

  MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  hDC=NULL; // Set DC To NULL

 }

 if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?

 {

  MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);

  hWnd=NULL; // Set hWnd To NULL

 }

 if (!UnregisterClass("OpenGL", hInstance)) // Are We Able To Unregister Class

 {

  MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

  hInstance=NULL; // Set hInstance To NULL

 }

 KillFont(); // Kill The Font

}

CreateGLWindow(), and WndProc() are the same.

The first change in WinMain() is the title that appears at the top of the window. It should now read "NeHe's Extensions, Scissoring, Token & TGA Loading Tutorial"

int WINAPI WinMain(HINSTANCE hInstance, // Instance

 HINSTANCE hPrevInstance, // Previous Instance

 LPSTR lpCmdLine, // Command Line Parameters

 int nCmdShow) // Window Show State

{

 MSG msg; // Windows Message Structure

 BOOL done=FALSE; // Bool Variable To Exit Loop

 // Ask The User Which Screen Mode They Prefer

 if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?", MB_YESNO|MB_ICONQUESTION) == IDNO) {

  fullscreen=FALSE; // Windowed Mode

 }

 // Create Our OpenGL Window

 if (!CreateGLWindow("NeHe's Token, Extensions, Scissoring & TGA Loading Tutorial", 640, 480, 16, fullscreen)) {

  return 0; // Quit If Window Was Not Created

 }

 while(!done) // Loop That Runs While done=FALSE

 {

  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting?

  {

   if (msg.message==WM_QUIT) // Have We Received A Quit Message?

   {

    done=TRUE; // If So done=TRUE

   } else // If Not, Deal With Window Messages

   {

    DispatchMessage(&msg); // Dispatch The Message

   }

  } else // If There Are No Messages

  {

   // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()

   if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?

   {

    done=TRUE; // ESC or DrawGLScene Signalled A Quit

   } else // Not Time To Quit, Update Screen

   {

    SwapBuffers(hDC); // Swap Buffers (Double Buffering)