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
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);
}
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
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!!!