Forum

Font rendering problem

Discuss programming topics that involve the OpenGL API.

Moderator: InsideQC Admins

Font rendering problem

Postby Zylyx_ » Sat Sep 05, 2009 7:19 pm

As expected, I ran into a problem with my new code implementation built on top of my last one.

Basicaly, I'm assigning the new font handle to my global font handle, g_hFont.

Then I create a new font using the windows CreateFont() function.

Then I use wglUseFontBitmaps() to trace the font glyphs and convert them into bitmaps. i then return all of this as a new list element/counter, to my global g_FontList variable.

Now, it's my DrawTextGL() function that might be the problem. The original function I based it on (th eone from Game Tutorials LLC), used a variable argument list to pass additional string information into the function. But I ripped that out because I didnt see any need for it (well, not at this point, anyways).

So what happens in this function is that I create a temp 256 char array. Then I position the text, then I push all of the current list elements in my glList using glPushAttrib(GL_LIST_BIT).
Then I set the list base element to the font list base counter (the global g_FontList variable).

Then I use the glCallLists() function. Note that I'm using strlen to get the size of the characters in my temp 256 char array, and i treat them as GL_UNSIGNED_BYTE, which is a character. Finaly I pop the attribute list using glPopAttrib().

However, all i'm getting is a blank screen....
No font what so ever!!

Maybe it's a simple glitch I overlooked for the moment, but I would really appreciate it if you guys here could give it your expert glance.

Perhaps it's my wrong understanding of GL Lists, because I treat them as STL vectors (in my mind), which I'm hoping is the correct understanding.

Anyways, here is the all mighty code (sorry fo rthe big chunks, lol).




gl_win32_core.h

Code: Select all
//This file contains all of the core Win32/OpenGL function prototypes, system includes and global variables required for setting up a basic
//windowed rendering environment for OpenGL application using Win32.

#ifndef _GL_WIN32_CORE_H_
#define _GL_WIN32_CORE_H_

//Library includes (preferably set this in the project->properties/option tab if available)
//#pragma comment(lib, "opengl32.lib")
//#pragma comment(lib, "glu32.lib")

//System includes
#include <windows.h>      // Must have for Windows platform builds
#include <tchar.h>         // Requires to convert each character in each string argument into a 2 byte character. Win32 treats all string characters as UNICODE.
#include <gl\gl.h>         // Microsoft OpenGL headers (version 1.1 by themselves)
#include <gl\glu.h>         // OpenGL Utilities

//OpenGL hRC specific
static GLfloat windowWidth;
static GLfloat windowHeight;                  

//Win32 specific global variables
static LPCTSTR lpszAppName = L"Swogle";
static HWND  g_hWnd;      //Window handle   
static RECT  g_rRect;      //Window rendering dimensions               
static HDC   g_hDC;         //GDI hardware device context            
static HGLRC g_hRC;         //Hardware renedeing contect for OpenGL   
static HINSTANCE g_hInstance; //App instance (id)

///////////////////////////////////
//Core Win32 function prototypes
///////////////////////////////////

//WinMain
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

//WindowProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam);

//Prog main loop
WPARAM MainLoop();

//Resiter and create new window
HWND CreateMyWindow(LPCTSTR strWindowName, int nWidth, int nHeight);

/////////////////////////////////////
//Core OpenGL function prototypes
////////////////////////////////////

//Set display format
void SetDCPixelFormat();

//Change window size
void ChangeSize(GLsizei w, GLsizei h);

//Add Init function for GL specific stuff

//This draws everything to the screen
void RenderScene();

//Free all memeory associated with the program
void DeInit();

#endif



gl_win32_core.cpp

Code: Select all
//This file contains all of the core Win32/OpenGL function implementations required for setting up a basic
//windowed rendering environment for OpenGL application using Win32.

#include "gl_win32_core.h"
#include "gl_win32_core_add.h"

//=======================================================================================================================================================
//=======================================================================================================================================================
//Core Win32 function implementations
//=======================================================================================================================================================
//=======================================================================================================================================================

/////////////////////////////////////
//WinMain function implementation
////////////////////////////////////
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
   //HWND hWnd; //Local window handle

   //Create new window
   g_hWnd = CreateMyWindow(lpszAppName, 800, 600);

   //If window handle is invalid, quit the program
   if(g_hWnd == NULL)
   {
      return TRUE;
   }

   g_hInstance = hInstance;

   //Initialize the program here
                                          
   //Run message loop and return the result
   return MainLoop();                  
}

//////////////////////////////////////////////
//CreateMyWindow() function implementation
//////////////////////////////////////////////
HWND CreateMyWindow(LPCTSTR strWindowName, int nWidth, int nHeight)
{
   HWND hWnd; //Local window handle
   WNDCLASS wc; //Window class that will be registered

   //clear the memory first
    memset(&wc, 0, sizeof(wc));
   
    //Set all of the attributes up for the window class & register it
    wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC; //CS_OWNDC: Tells Windows to create a device context just for this window
    wc.lpfnWndProc = WndProc;
   wc.cbClsExtra      = 0;
   wc.cbWndExtra      = 0;
    wc.hInstance = g_hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = NULL; //No need for background brush when using OpenGL
   wc.lpszMenuName = NULL; //No menus either
    wc.lpszClassName = lpszAppName;
   
   //Now, register the windows class with Windows
    RegisterClass(&wc);                     

   //Create the main application window
   hWnd = CreateWindow(
                     lpszAppName,
                     strWindowName,
                     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, //WS_CLIPCHILDREN & WS_CLIPSIBLINGS are used to prevent
                     CW_USEDEFAULT,                                  //the OpenGL rendering context from rendering into other 
                     CW_USEDEFAULT,                                  //windows. An OpenGL rendering context must be associated
                     nWidth,                                        //with only one active window at a time.
                     nHeight,
                     NULL,
                     NULL,
                     g_hInstance,
                     NULL
                  );

   //If there is no window handle...
   if(!hWnd)
   {
      return NULL;
   }

   // Show the window
   ShowWindow(hWnd, SW_SHOWNORMAL);   

   // Draw the window
   UpdateWindow(hWnd);                           

   //Sets Keyboard Focus To The Window
   SetFocus(hWnd);                                 

   return hWnd;
}

/////////////////////////////////////////
//WindowProc() function implementation
////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg, WPARAM wParam, LPARAM lParam)
{
   switch(nMsg)
   {
      //Setup the window for OpenGL here
   case WM_CREATE:
      {
         //Store device context
         g_hDC = GetDC(hWnd);

         //Select the pixel format
         SetDCPixelFormat();

         //Create the rendering context and make it current
         g_hRC = wglCreateContext(g_hDC);
         wglMakeCurrent(g_hDC, g_hRC);

         //Create a timer that calls specific functions 30 times a second
         SetTimer(hWnd, 30, 1, NULL);

         //Creat the font
         g_FontList = MakeGLFont((LPCTSTR)"Arial", FONT_HEIGHT);

         return 0;
      }
      //When the window is destroyed, clean up after OpenGL
   case WM_DESTROY:
      {
         //Kill timer
         KillTimer(hWnd, 101);

         //Delete any OpenGL-allocated memory here
         DestroyFont();   

         //Deselect current rendering context and delete it
         wglMakeCurrent(g_hDC, NULL);
         wglDeleteContext(g_hRC);

         //Terminate program after window is destroyed
         PostQuitMessage(0);

         return 0;
      }
      //Change window size appropriately (keeping all clipping bounds for the viewport and rendering volume in order)
   case WM_SIZE:
      {
         ChangeSize(LOWORD(lParam), HIWORD(lParam));
         return 0;
      }
      //Call the timer function here. The MoveSquare() function goes here, and after it is called, the window is
      //invalidated so that it will be drawn again. This happens 30 times a second.
   case WM_TIMER:
      {
         //Anim code goes here

         //Invalidate the rect
         InvalidateRect(hWnd, NULL, FALSE);

         return 0;
      }
      //The WM_PAINT message is sent by Windows everytime the screen needs to be updated. And that's what we do here
   case WM_PAINT:
      {
         //Render current scene
         RenderScene();

         //Swap buffers
         SwapBuffers(g_hDC);

         //Validate the newly painted client area
         ValidateRect(hWnd, NULL);

         return 0;
      }
   default:
      {
         return DefWindowProc(hWnd, nMsg, wParam, lParam);
      }
   }
   return 0;
}

///////////////////////////////////////
//MainLoop() function implementation
//////////////////////////////////////
WPARAM MainLoop()
{
   MSG msg;
   
   while(1)
   {
      if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) //Peek to see if there are any messages in the que...
      {
         if (!GetMessage(&msg, NULL, 0, 0)) //Same as above, except the message get's removed from the message queue
         {
            return msg.wParam; //If there is no message to get, return wParam, which returns a 0 upon normal program termination
         }

         //do the rest
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
      //else
      //{
         //call game logic code here
      //}
   }
   
   //Window cleanup code goes here...
   DeInit();
   
   //Return the exit code for the application.
   return msg.wParam;
}

//=======================================================================================================================================================
//=======================================================================================================================================================
//Core OpenGL function implementations
//=======================================================================================================================================================
//=======================================================================================================================================================

//////////////////////////////////////////////////////////////////////////
//Hardware device context pixel format setting function implementation
/////////////////////////////////////////////////////////////////////////
void SetDCPixelFormat()
{
   int nPixelFormat;

   static PIXELFORMATDESCRIPTOR pfd =
   {
      sizeof(PIXELFORMATDESCRIPTOR),
      1,
      PFD_DRAW_TO_WINDOW |
      PFD_SUPPORT_OPENGL |
      PFD_DOUBLEBUFFER,
      PFD_TYPE_RGBA,
      32,
      0,0,0,0,0,0,
      0,0,
      0,0,0,0,0,
      24,
      0,
      0,
      0,
      0,
      0,0,0
   };

   //Choose a best matched pixel format fitting the above description
   nPixelFormat = ChoosePixelFormat(g_hDC, &pfd);

   //Set the pixel format for the HDC
   SetPixelFormat(g_hDC, nPixelFormat, &pfd);
}

///////////////////////////////////////////
//RenderScene() function implementation 
//////////////////////////////////////////
void RenderScene()
{
   //Set the background clearing color to gray
   glClearColor(0.25f, 0.25f, 0.25f, 1.0f);

   //Clear the screen (with the current clearing color and the depth buffer
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   

   //Reset the identity matrix
   glLoadIdentity();   

   //Text color to draw
   glColor3f(1, 0, 0);   

   //Draw the text
   DrawTextGL(50, 25, (LPCTSTR)"TTF Test");
}

///////////////////////////////////////
//ChangeSize function implementation
//////////////////////////////////////
void ChangeSize(GLsizei w, GLsizei h)
{
   GLfloat aspectRatio; //Aspect artio for drawing the window

   //Avoid dividing by zero
   if(h == 0)
   {
      h = 1;
   }

   //Set viewport to window dimenstions (0, 0 is the clipping region; w, h are the width and height of the viewport in pixels
   glViewport(0, 0, w, h);

   //Reset coordinate system
   glMatrixMode(GL_PROJECTION);//Define projection matrix
   glLoadIdentity();//Load identity matrix for GL_PROJECTION (reset matrix)

   aspectRatio = (GLfloat)w / (GLfloat)h;

   if(w <= h)
   {
      windowWidth = 100;
      windowHeight = 100 / aspectRatio;
      glOrtho(-100.0, 100.0, -windowHeight, windowHeight, 1.0, -1.0);
   }
   else
   {
      windowWidth = 100 * aspectRatio;
      windowHeight = 100;
      glOrtho(-windowWidth, windowWidth, -100.0, 100.0, 1.0, -1.0);
   }

   glMatrixMode(GL_MODELVIEW);//Set the matrix mode to effect all of the current geometry that is drawn
   glLoadIdentity();//Reset the matrix
}

/////////////////////////////////////////////////
//Free all memeory associated with the program
////////////////////////////////////////////////
void DeInit()
{
   //Add all cleanup code associated with the window here

   //Unregister the window class
   UnregisterClass(lpszAppName, g_hInstance);
}


gl_win32_core_add.h

Code: Select all
//This header file includes additional function prototypes for the gl_win32_core template.
//This includes font rendering, input and sound.

#ifndef _GL_WIN32_CORE_ADD_H_
#define _GL_WIN32_CORE_ADD_H_

#include "gl_win32_core.h"

//////////////////////////////////////////////////////////////////////
//Font rendering function prototypes, defines and global variables
/////////////////////////////////////////////////////////////////////

static UINT g_FontList = 0; //Counter for the font lists (257 in total).
static HFONT g_hOldFont; //Font handle for old font that gets saved when a new font is selected.

#define MAX_CHARS 256
#define FONT_HEIGHT 32

//Create a native windows font and return the display list counter
UINT MakeGLFont(LPCWSTR strFontName, GLsizei height);

//Set drawing position for the text
void PosText(GLsizei x, GLsizei y);

//Draw the text
void DrawTextGL(GLsizei x, GLsizei y, LPCTSTR strString);

//Free the display list associated with the font
void DestroyFont();

#endif


gl_win32_core_add.cpp

Code: Select all
//This file includes the implementations of the additional gl_win32_core template, gl_win32_core_add.h
//All the implementations of functions ofr font rendering, input and sound playback go here.

#include "gl_win32_core_add.h"

//=======================================================================================================================================================
//=======================================================================================================================================================
//Font rendering function implementations
//=======================================================================================================================================================
//=======================================================================================================================================================

/////////////////////////////////
//Font function implementation
/////////////////////////////////
UINT MakeGLFont(LPCWSTR strFontName, GLsizei height)
{
   UINT tempFontList = 0; //Temp font list counter.
   HFONT hFont; //Local font handle.

   //Generate a list to hold all of the font characters
   tempFontList = glGenLists(MAX_CHARS);

   //Create the font, using the Windows CreateFont() function.
   //Read MSDN's artilce on CreateFont() for parameter info.
   hFont = CreateFont(   FONT_HEIGHT,
                  0,
                  0,
                  0,
                  FW_NORMAL,
                  FALSE,
                  FALSE,
                  FALSE,
                  ANSI_CHARSET,
                  OUT_TT_PRECIS,
                  CLIP_DEFAULT_PRECIS,
                  ANTIALIASED_QUALITY,
                  FF_DONTCARE|DEFAULT_PITCH,
                  strFontName);

   //Select the new font into the global hdc.
   //Store old font to select it back inorder to avoid memory leaks.
   //Thsi just catches and keeps the font until it is destroyed.
   g_hOldFont = (HFONT)SelectObject(g_hDC, hFont);

   //The next wgl specific function does the actual conversion of the font glyphs into bitmap characters.
   //This builds 255 bitmapped font characters.
   //Parameters:
   // g_hDC - The hdc that holds the font
   // 0 - First ASCII glyph to be bitmapped
   // MAX_CHARS - 1 - Last ASCII glyph to be bitmapped
   // tempFontList - The starting display list
   wglUseFontBitmaps(g_hDC, 0, MAX_CHARS - 1, tempFontList);

   //Return the display list counter to use later on
   return tempFontList;
}

/////////////////////////////////////////////
//Font positioning function implementation
/////////////////////////////////////////////
void PosText(GLsizei x, GLsizei y)
{
   //Save the current view port. This saves the transformation matirx and the current viewport settings.
   glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT);

   //Create a new projection and modelview matrix for the font to use
   glMatrixMode(GL_PROJECTION);                  
   glPushMatrix();                              
   glLoadIdentity();                           
   glMatrixMode(GL_MODELVIEW);                  
   glPushMatrix();                              
   glLoadIdentity();   

   //Flip the 0 y coord position to the top of the screen.
   //Add 25 to the y coord in windowed mode to make sure the font doesnt go off screen
   y = (GLsizei)windowHeight - FONT_HEIGHT - y;

   //Create a new viewport for the font to be drawn into
   glViewport(x - 1, y - 1, 0, 0);

   //Set the text drawing position
   glRasterPos4f(0, 0, 0, 1);

   //After text has been positioned, put everything back to normal
   glPopMatrix();                              
   glMatrixMode(GL_PROJECTION);                  
   glPopMatrix();                              
   
   //Restores the TRANSFORM and VIEWPORT attributes
   glPopAttrib();                              
}

/////////////////////////////////////////////
//Font drawing function implementation
/////////////////////////////////////////////
void DrawTextGL(GLsizei x, GLsizei y, LPCTSTR strString)
{
   char tmp_strText[256]; //Holds 256 unicode friendly characters

   //Check if a string was given
   if(strString == NULL)
   {
      return;
   }

   //First, position the text using the above function
   PosText(x, y);

   //Save the current list base
   glPushAttrib(GL_LIST_BIT);

   //Set the list base to the font list base counter
   glListBase(g_FontList);

   //Render the font.
   //Pass in the length of the string, character data types (unsigned int's) and the character array.
   //Note: Check if OpenGL is friendly with LPCTSTR type character strings....
   glCallLists(strlen(tmp_strText), GL_UNSIGNED_BYTE, tmp_strText);

   glPopAttrib();   
}

/////////////////////////////////////////
//Destroy font function implementation
////////////////////////////////////////
void DestroyFont()                              
{
   // Free the display list
   glDeleteLists(g_FontList, MAX_CHARS);      

   // Select the old font back to avoid memory leaks
   SelectObject(g_hDC, g_hOldFont);                  
}

                  



Thank you in advance!!! :)
....noodle...
Zylyx_
 
Posts: 111
Joined: Wed Dec 05, 2007 6:52 pm
Location: scotland, uk

Return to OpenGL Programming

Who is online

Users browsing this forum: No registered users and 1 guest