Improving my OpenGl Win32 Frames Per Second Source

I am trying to make a frames per second OpenGl engine to use with all my games. I had previously made it in just Win32 with graphics but I found out how to link OpenGl and I have some problems and questions I would like answered:
1) Why does my screen go black while resizing? I tried to put my draw() function in the WM_SIZE message, but I get errors that it can't find the HDC, so I can't add the SwapBuffer(HDC) in there. Any work arounds?
2) What is the most efficient way of drawing text on the screen? I am unaware that OpenGl doesn't handle fonts so I have to use bitmaps or another method.
3) How do I keep the FPS stay while resizing, as it looks like it lags after you finish resizing while it actually doesn't, it just thinks it is. This is because the window freezes while you're resizing, so it think there's a large interval of time between the next frames so that's why it thinks it's lagging. I tried to record the time spent while in the WM_SIZE and add the interval to the elapsed time, but it doesn't work. Maybe I'm just stupid? By the way, I used the TextOut function to find the number of FPS which is recorded in dwFPS.

My Source is here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include "fps.h"
#include <gl/gl.h>
#include <math.h>
#define PI 3.14159265358979323846f

static TCHAR szWindowClass[] = _T("fpsopenglapp");
static TCHAR szTitle[] = _T("FPS OpenGl Engine");

HINSTANCE hInst;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);
void glEnable2D();
void glDisable2D();
void DrawCircle(float cx, float cy, float r, int num_segments) ;
void setScreenSize(HWND hWnd,long swidth,long sheight);
void draw();

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
    WNDCLASSEX wcex;
	HDC hDC;
	HGLRC hRC;
	MSG msg;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wcex.lpszMenuName   = NULL;
	wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

    if (!RegisterClassEx(&wcex)){
		MessageBox(NULL,_T("Register Class Failed"),_T("Error 1"),NULL);
		return 1;
    }
    hInst = hInstance;
	HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 256, 192,
        NULL, NULL, hInstance, NULL);
    if (!hWnd){
        MessageBox(NULL,_T("Window Creation Failed"),_T("Error 2"),NULL);
		return 1;
    }
	setScreenSize(hWnd, 256,192);
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
	EnableOpenGL( hWnd, &hDC, &hRC );

    msg.message = (~WM_QUIT);
	while(msg.message != WM_QUIT){
	while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)== true){
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		draw();
	SwapBuffers( hDC );
		calculateFPS();
		setFPS(hWnd);
	}
	DisableOpenGL( hWnd, hDC, hRC );
	DestroyWindow( hWnd );
    return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    PAINTSTRUCT ps;
    HDC hdc;
	draw();
    switch (message)
    {
	case WM_CREATE:
		return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
	case WM_SIZE:
		RECT rect;
		GetClientRect(hWnd, &rect); 
		glViewport(0,0,rect.right,rect.bottom);
		return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC){
	PIXELFORMATDESCRIPTOR pfd;
	int format;
	*hDC = GetDC( hWnd );
	ZeroMemory( &pfd, sizeof( pfd ) );
	pfd.nSize = sizeof( pfd );
	pfd.nVersion = 1;
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 24;
	pfd.cDepthBits = 16;
	pfd.iLayerType = PFD_MAIN_PLANE;
	format = ChoosePixelFormat( *hDC, &pfd );
	SetPixelFormat( *hDC, format, &pfd );
	*hRC = wglCreateContext( *hDC );
	wglMakeCurrent( *hDC, *hRC );
	glEnable(GL_POINT_SMOOTH);
}
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC){
	wglMakeCurrent( NULL, NULL );
	wglDeleteContext( hRC );
	ReleaseDC( hWnd, hDC );
}
void glEnable2D(){
	GLint iViewport[4];
	glGetIntegerv( GL_VIEWPORT, iViewport );
	glMatrixMode( GL_PROJECTION );
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0,256,192,0, -1, 1 );
	glMatrixMode( GL_MODELVIEW );
	glPushMatrix();
	glLoadIdentity();
	glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT );
	glDisable( GL_DEPTH_TEST );
	glDisable( GL_LIGHTING );
	glTranslatef(0.375, 0.375, 0);
}
void glDisable2D(){
	glPopAttrib();
	glMatrixMode( GL_PROJECTION );
	glPopMatrix();
	glMatrixMode( GL_MODELVIEW );
	glPopMatrix();
}
void setScreenSize(HWND hWnd,long swidth,long sheight){
	RECT sRect;
	RECT wRect;
	GetClientRect(hWnd,&sRect);
	GetWindowRect(hWnd,&wRect);
	MoveWindow(hWnd,NULL,NULL,swidth+((wRect.right-wRect.left)-sRect.right),
	sheight+(wRect.bottom-wRect.top)-sRect.bottom,FALSE);
}

void DrawCircle(float cx, float cy, float r, int num_segments) {
	glBegin(GL_POLYGON);
	for(int i=1.0;i<=num_segments;++i){
		glVertex2f(120+32*cosf((i/30.0)*360*0.0174532925),
		120-32*sinf((i/30.0)*360*0.0174532925));
	}
	glEnd();
}
void draw(){
	glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glEnable2D();
	glColor3f(1,0,0);
	glBegin(GL_QUADS);
	glVertex2f(10,80);
	glVertex2f(180,10);
	glVertex2f(180,180);
	glVertex2f(10,180);
	glEnd();
	glColor3f(0,0,1);
	DrawCircle(120,120,20,30.0);
	glColor3f(0,0,1);
	glBegin(GL_QUADS);
	glVertex2f(10,10);
	glVertex2f(252,10);
	glVertex2f(40,40);
	glVertex2f(10,40);
	glEnd();
	glDisable2D();
}

And fps.h is this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#pragma once;
#include <stdio.h>
DWORD dwFrames = 0;
DWORD dwCurr = GetTickCount();
DWORD dwLast = 0;
DWORD dwElapse = 0;
DWORD dwFPS = 0;
DWORD dwFPSmax = 30;

void calculateFPS(){
	if (dwFrames<30){
		dwFrames+=1;
	}
	dwCurr = GetTickCount();
	dwElapse = dwCurr - dwLast;
	if (dwElapse >= 1000){
		dwFPS = dwFrames;
		dwLast = dwCurr;
		dwFrames = 0;
	}
}

void setFPS(HWND hWnd){
	Sleep(30);
}

I would greatly thank you if you improve this in any way. I want the FPS to be set at 30 frames per second. Also, I've been reading that the Sleep() function isn't good. Is this true and why?
What is the most efficient way of drawing text on the screen?
If you're using raster fonts, load as a texture and map it to polygons you'll draw to the screen.
If you're using outline fonts, rasterize first and then load to a texture.
Why does my screen go black while resizing? I tried to put my draw() function in the WM_SIZE message, but I get errors that it can't find the HDC, so I can't add the SwapBuffer(HDC) in there. Any work arounds?
@line 30 change it to wcex.style = CS_OWNDC;
If you're using raster fonts, load as a texture and map it to polygons you'll draw to the screen.
If you're using outline fonts, rasterize first and then load to a texture.

How do I load an image? I'm guessing I'd have to save all the characters in one texture and then separate it to draw the text? I'm confused about this whole thing and can't find anything useful online that doesn't confuse me.

Oh and it should be noted that I'm drawing my OpenGl in a 2D view if anyone hasn't noticed.

@line 30 change it to wcex.style = CS_OWNDC;

Worked great, thanks, I understand it now.
How do I load an image?
What do you mean? How to load a texture to VRAM or how to load a bitmap to system memory? The former involves a few OpenGL calls, most importantly glTexImage2D(). The latter depends on the format you're using.

I'm guessing I'd have to save all the characters in one texture and then separate it to draw the text?
When you map the texture to the polygon, you'll tell OGL where on the texture each vertex goes with glTexCoord2*(), so even though you're mapping the whole texture to the polygon, drawing the polygon won't necessarily draw the whole texture.

I recommend you get yourself an OpenGL reference. Or you can use the online reference: http://www.opengl.org/sdk/docs/man/
What are the advantages and disadvantages to using VRAM compared to loading a bitmap to system memory? And how do you load to VRAM?
What are the advantages and disadvantages to using VRAM compared to loading a bitmap to system memory?
No. First you have to load the bitmap to RAM and then you can load it to VRAM if you want to use it as a texture.

And how do you load to VRAM?
Did you read my post? Because I flat out told you the function that does that.

How to do all this is covered in great detail all over the Internet. The NeHe tutorials are pretty good.
Last edited on
No. First you have to load the bitmap to RAM and then you can load it to VRAM if you want to use it as a texture...

Did you read my post? Because I flat out told you the function that does that.


I'm sorry, I was just confused a bit. I'll go check out NeHe's tutorials and I'll return when I have legit questions.

EDIT: Nehe's tutorials use Gluax.h which is deprecated?
Last edited on
Topic archived. No new replies allowed.