Inside3D!
     

Font rendering problem

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> OpenGL Programming
View previous topic :: View next topic  
Author Message
Zylyx_



Joined: 05 Dec 2007
Posts: 111
Location: scotland, uk

PostPosted: Sat Sep 05, 2009 7:19 pm    Post subject: Font rendering problem Reply with quote

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:

//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:

//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:

//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:

//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!!! Smile
_________________
....noodle...
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> OpenGL Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group