2D字体贴图的贴法和一般的贴图纹理有点小区别,可以先看看我们需要用到的字体贴图纹理。
在BuildFont()函数中,我们对图片进行分割为16X16,则创建256个列表。这段代码表示每次把图片上的一个符号存进列表中。
1 glBegin(GL_QUADS); 2 glTexCoord2f(cx, 1 - cy - 0.0625); // Texture coord (bottom left) 1/16 == 0.0625 3 glVertex2i(0, 0); // Vertex coord (bottom left) 4 5 glTexCoord2f(cx + 0.0625f, 1 - cy - 0.0625); // Texture coord (bottom right) 6 glVertex2i(16, 0); // Vertex coord (bottom right) 7 8 glTexCoord2f(cx + 0.0625f, 1 - cy); // Texture coord (top right) 9 glVertex2i(16, 16); // Vertex coord (top right) 10 11 glTexCoord2f(cx, 1 - cy); // Texture coord (top left) 12 glVertex2i(0, 16); // Vertex coord (top left) 13 glEnd();
在glPrint()函数中我们对先前创建的256个列表进行选择,是否是大小写的代码为:
1 glListBase(base - 32 + (128 * set)); // Choose the font set (0 or 1)
具体选择哪个字符的代码为:
1 glCallLists(strlen(string), GL_UNSIGNED_BYTE, string); // With the font to the screen
glPrint()函数中的glOrtho()函数(multiply the current matrix with an orthographic matrix)、glMatrixMode()函数(specify which matrix is the current matrix)、glListBase()函数(set the display-list base for glCallLists)、glCallLists()函数(execute a list of display lists)在OpenGL的官方文档被解释的很详细。
字体的位置与颜色变化用到了一些sin,cos函数。
代码如下,同样修改部分位于双行星号内。
1 #include <windows.h> 2 #include <stdio.h> 3 #include <math.h> 4 #include <gl/glew.h> 5 #include <gl/glut.h> 6 #include <GL/GLUAX.H> 7 #pragma comment(lib, "legacy_stdio_definitions.lib") 8 /* 9 * Every OpenGL program is linked to a Rendering Context. 10 * A Rendering Context is what links OpenGL calls to the Device Context. 11 * In order for your program to draw to a Window you need to create a Device Context. 12 * The DC connects the Window to the GDI (Graphics Device Interface). 13 */ 14 15 HGLRC hRC = NULL; // Permanent rendering context 16 HDC hDC = NULL; // Private GDI device context 17 HWND hWnd = NULL; // Holds our window handle 18 HINSTANCE hInstance; // Holds the instance of the application 19 20 /* 21 * It's important to make this global so that each procedure knows if 22 * the program is running in fullscreen mode or not. 23 */ 24 25 bool keys[256]; // Array used for the keyboard routine 26 bool active = TRUE; // Window active flag set to TRUE by default 27 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default 28 29 /******************************************************************************************************************************************/ 30 /******************************************************************************************************************************************/ 31 GLuint base; 32 GLuint texture[2]; 33 GLuint loop; 34 35 GLfloat cnt1; 36 GLfloat cnt2; 37 /******************************************************************************************************************************************/ 38 /******************************************************************************************************************************************/ 39 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc 40 41 AUX_RGBImageRec* LoadBMP(char* Filename) 42 { 43 FILE* File = NULL; 44 45 if (!Filename) { 46 return NULL; 47 } 48 49 File = fopen(Filename, "r"); 50 if (File) { 51 fclose(File); 52 return auxDIBImageLoad(Filename); 53 } 54 55 return NULL; 56 } 57 58 int LoadGLTextures() 59 { 60 int Status = FALSE; 61 62 /******************************************************************************************************************************************/ 63 /******************************************************************************************************************************************/ 64 AUX_RGBImageRec* TextureImage[2]; 65 66 memset(TextureImage, 0, sizeof(void*) * 2); 67 68 if ((TextureImage[0] = LoadBMP("2.bmp")) && 69 (TextureImage[1] = LoadBMP("1.bmp"))) { 70 Status = TRUE; 71 glGenTextures(2, &texture[0]); 72 73 for (loop = 0; loop < 2; ++loop) { 74 glBindTexture(GL_TEXTURE_2D, texture[loop]); 75 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 76 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 77 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 78 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data); 79 } 80 } 81 82 for (loop = 0; loop < 2; ++loop) { 83 if (TextureImage[loop]) { 84 if (TextureImage[loop]->data) { 85 free(TextureImage[loop]->data); 86 } 87 free(TextureImage[loop]); 88 } 89 } 90 return Status; 91 } 92 93 GLvoid BuildFont(GLvoid) 94 { 95 float cx; // Holds ur X character coord 96 float cy; // Holds ur Y character coord 97 base = glGenLists(256); 98 glBindTexture(GL_TEXTURE_2D, texture[0]); 99 for (loop = 0; loop < 256; ++loop) { 100 cx = float(loop % 16) / 16.0f; 101 cy = float(loop / 16) / 16.0f; 102 glNewList(base + loop, GL_COMPILE); 103 glBegin(GL_QUADS); 104 glTexCoord2f(cx, 1 - cy - 0.0625); // Texture coord (bottom left) 1/16 == 0.0625 105 glVertex2i(0, 0); // Vertex coord (bottom left) 106 107 glTexCoord2f(cx + 0.0625f, 1 - cy - 0.0625); // Texture coord (bottom right) 108 glVertex2i(16, 0); // Vertex coord (bottom right) 109 110 glTexCoord2f(cx + 0.0625f, 1 - cy); // Texture coord (top right) 111 glVertex2i(16, 16); // Vertex coord (top right) 112 113 glTexCoord2f(cx, 1 - cy); // Texture coord (top left) 114 glVertex2i(0, 16); // Vertex coord (top left) 115 glEnd(); 116 117 glTranslated(10, 0, 0); 118 glEndList(); 119 } 120 } 121 122 GLvoid KillFont(GLvoid) 123 { 124 glDeleteLists(base, 256); 125 } 126 127 GLvoid glPrint(GLint x, GLint y, char* string, int set) 128 { 129 if (set > 1) { 130 set = 1; 131 } 132 glBindTexture(GL_TEXTURE_2D, texture[0]); 133 glDisable(GL_DEPTH_TEST); 134 135 glMatrixMode(GL_PROJECTION); // Select projection matrix 136 glPushMatrix(); // Store the projection matrix 137 glLoadIdentity(); 138 139 glOrtho(0, 640, 0, 480, -1, 1); // Set ortho screen 140 141 glMatrixMode(GL_MODELVIEW); // Select modeview matrix 142 glPushMatrix(); 143 glLoadIdentity(); 144 145 glTranslated(x, y, 0); 146 glListBase(base - 32 + (128 * set)); // Choose the font set (0 or 1) 147 148 glCallLists(strlen(string), GL_UNSIGNED_BYTE, string); // With the font to the screen 149 150 glMatrixMode(GL_PROJECTION); 151 glPopMatrix(); // Restore the old projection matrix 152 153 glMatrixMode(GL_MODELVIEW); 154 glPopMatrix(); 155 156 glEnable(GL_DEPTH_TEST); 157 } 158 /******************************************************************************************************************************************/ 159 /******************************************************************************************************************************************/ 160 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize and initialize the GL window 161 { 162 if (height == 0) { // Prevent a divide by zero by 163 height = 1; // Making height equal one 164 } 165 166 glViewport(0, 0, width, height); // Reset the current viewport 167 168 /* 169 * The following lines set the screen up for a perspective view. 170 * Meaning things in the distance get smaller. This creates a realistic looking scene. 171 * The perspective is calculated with a 45 degree viewing angle based on 172 * the windows width and height. The 0.1f, 100.0f is the starting point and 173 * ending point for how deep we can draw into the screen. 174 * 175 * The projection matrix is responsible for adding perspective to our scene. 176 * glLoadIdentity() restores the selected matrix to it's original state. 177 * The modelview matrix is where our object information is stored. 178 * Lastly we reset the modelview matrix. 179 */ 180 181 glMatrixMode(GL_PROJECTION); // Select the projection matrix 182 glLoadIdentity(); // Reset the projection matrix 183 184 // Calculate the aspect ratio of the window 185 gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 186 187 glMatrixMode(GL_MODELVIEW); // Seclet the modelview matrix 188 glLoadIdentity(); // Reset the modelview matrix 189 } 190 /******************************************************************************************************************************************/ 191 /******************************************************************************************************************************************/ 192 int InitGL(GLvoid) // All setup for OpenGL goes here 193 { 194 /* 195 * Smooth shading blends colors nicely across a polygon, and smoothes out lighting. 196 */ 197 198 if (!LoadGLTextures()) { 199 return FALSE; 200 } 201 BuildFont(); 202 203 glEnable(GL_TEXTURE_2D); 204 glShadeModel(GL_SMOOTH); // Enables smooth shading 205 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black background 206 207 glClearDepth(1.0f); // Depth buffer setup 208 209 glDepthFunc(GL_LEQUAL); 210 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 211 212 return TRUE; 213 } 214 /* 215 * For now all we will do is clear the screen to the color we previously decided on, 216 * clear the depth buffer and reset the scene. We wont draw anything yet. 217 */ 218 int DrawGLScene(GLvoid) // Here's where we do all the drawing 219 { 220 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and the depth buffer 221 glLoadIdentity(); 222 223 glTranslatef(0.0f, 0.0f, -5.0f); 224 225 glBindTexture(GL_TEXTURE_2D, texture[1]); 226 227 glRotatef(45.0f, 0.0f, 0.0f, 1.0f); 228 glRotatef(cnt1 * 30.0f, 1.0f, 1.0f, 0.0f); 229 230 glDisable(GL_BLEND); 231 glColor3f(1.0f, 1.0f, 1.0f); 232 233 glBegin(GL_QUADS); 234 glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, 1.0f); 235 glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 1.0f); 236 glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, -1.0f); 237 glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, -1.0f); 238 glEnd(); 239 240 glRotatef(90.0f, 1.0f, 1.0f, 0.0f); 241 glBegin(GL_QUADS); 242 glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, 1.0f); 243 glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 1.0f); 244 glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, -1.0f); 245 glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, -1.0f); 246 glEnd(); 247 248 glEnable(GL_BLEND); 249 glLoadIdentity(); 250 251 glColor3f(1.0f * float(cos(cnt1)), 1.0f * float(sin(cnt2)), 1.0f - 0.5f * float(cos(cnt1 + cnt2))); 252 glPrint(int((280 + 250 * cos(cnt1))), int(235 + 200 * sin(cnt2)), "ME", 0); 253 254 glColor3f(1.0f * float(sin(cnt2)), 1.0f - 0.5f * float(cos(cnt1 + cnt2)), 1.0f * float(cos(cnt1))); 255 glPrint(int((280 + 230 * cos(cnt2))), int(235 + 200 * sin(cnt1)), "OpenGL", 1); 256 257 glColor3f(0.0f, 0.0f, 1.0f); 258 glPrint(int(240 + 200 * cos((cnt2 + cnt1) / 5)), 2, "ME", 0); 259 260 glColor3f(1.0f, 1.0f, 1.0f); 261 glPrint(int(240 + 200 * cos((cnt2 + cnt1) / 5)), 2, "ME", 0); 262 263 cnt1 += 0.001f; 264 cnt2 += 0.00081f; 265 return TRUE; // everthing went OK 266 } 267 /******************************************************************************************************************************************/ 268 /******************************************************************************************************************************************/ 269 /* 270 * The job of KillGLWindow() is to release the Rendering Context, 271 * the Device Context and finally the Window Handle. 272 */ 273 274 GLvoid KillGLWindow(GLvoid) // Properly kill the window 275 { 276 if (fullscreen) { // Are we in fullscreen mode 277 278 /* 279 * We use ChangeDisplaySettings(NULL,0) to return us to our original desktop. 280 * After we've switched back to the desktop we make the cursor visible again. 281 */ 282 283 ChangeDisplaySettings(NULL, 0); // if so switch back to the desktop 284 ShowCursor(TRUE); // Show mouse pointer 285 } 286 287 if (hRC) { // Do we have a rendering context 288 if (!wglMakeCurrent(NULL, NULL)) { // Are we able to release the DC and RC contexts 289 MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 290 } 291 292 if (!wglDeleteContext(hRC)) { // Are we able to delete the RC 293 MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 294 hRC = NULL; // Set RC to NULL 295 } 296 297 if (hDC && !ReleaseDC(hWnd, hDC)) { // Are we able to release the DC 298 MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 299 hDC = NULL; // Set DC to NULL 300 } 301 if (hWnd && !DestroyWindow(hWnd)) { // Are we able to destroy the window 302 MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 303 hWnd = NULL; // Set hWnd to NULL 304 } 305 306 if (!UnregisterClass("OpenGL", hInstance)) { // Are we able to unregister class 307 MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 308 hInstance = NULL; // Set hInstance to NULL 309 } 310 } 311 /******************************************************************************************************************************************/ 312 /******************************************************************************************************************************************/ 313 KillFont(); 314 /******************************************************************************************************************************************/ 315 /******************************************************************************************************************************************/ 316 } 317 318 /* 319 * The next section of code creates our OpenGL Window. 320 */ 321 322 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) 323 { 324 /* 325 * Find a pixel format that matches the one we want 326 */ 327 GLuint PixelFormat; // Holds the result after serching for a match 328 329 /* 330 * Before you create a window, you MUST register a Class for the window 331 */ 332 WNDCLASS wc; // Windows class structure 333 334 /* 335 * dwExStyle and dwStyle will store the Extended and normal Window Style Information. 336 */ 337 DWORD dwExStyle; // Window extend style 338 DWORD dwStyle; // Window style 339 340 RECT WindowRect; // Grabs rectangle upper left/lower right values 341 WindowRect.left = (long)0; // Set left value to 0 342 WindowRect.right = (long)width; // Set right value to requested width 343 WindowRect.top = (long)0; // Set top value to 0 344 WindowRect.bottom = (long)height; // Set bottom value to requested height 345 346 fullscreen = fullscreenflag; // Set the global fullscreen flag 347 348 /* 349 * The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 350 * CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 351 * WndProc is the procedure that watches for messages in our program. 352 * No extra Window data is used so we zero the two fields. Then we set the instance. 353 * Next we set hIcon to NULL meaning we don't want an ICON in the Window, 354 * and for a mouse pointer we use the standard arrow. The background color doesn't matter 355 * (we set that in GL). We don't want a menu in this Window so we set it to NULL, 356 * and the class name can be any name you want. I'll use "OpenGL" for simplicity. 357 */ 358 hInstance = GetModuleHandle(NULL); // Grab an instance for our window 359 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on move, and own DC for window 360 wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc handles message 361 wc.cbClsExtra = 0; // No extra window date 362 wc.cbWndExtra = 0; // No extra window date 363 wc.hInstance = hInstance; // set the instance 364 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load the default icon 365 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer 366 wc.hbrBackground = NULL; // No background requried for GL 367 wc.lpszMenuName = NULL; // We don't want a menu 368 wc.lpszClassName = "OpenGL"; // set the class name 369 370 if (!RegisterClass(&wc)) { // Attempt to register the window class 371 MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 372 return FALSE; // Exit and return false 373 } 374 375 if (fullscreen) { // attempt fullsreen model 376 377 /* 378 T* here are a few very important things you should keep in mind when switching to full screen mode. 379 * Make sure the width and height that you use in fullscreen mode is the same as 380 * the width and height you plan to use for your window, and most importantly, 381 * set fullscreen mode BEFORE you create your window. 382 */ 383 DEVMODE dmScreenSettings; // Device mode 384 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared 385 dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size of devmode structure 386 dmScreenSettings.dmPelsWidth = width; // Select window width 387 dmScreenSettings.dmPelsHeight = height; // Select window height 388 dmScreenSettings.dmBitsPerPel = bits; // Select bits per pixel 389 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 390 391 /* 392 * In the line below ChangeDisplaySettings tries to switch to a mode that matches 393 * what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 394 * because it's supposed to remove the start bar at the bottom of the screen, 395 * plus it doesn't move or resize the windows on your desktop when you switch to 396 * fullscreen mode and back. 397 */ 398 //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar 399 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { 400 //If the mode fails, offer two options. Quit or run in a window 401 if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use" 402 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) 403 { 404 fullscreen = FALSE; // Select windowed mode (fullscreen=FLASE) 405 } 406 else { 407 // Pop up a message box letting user know the programe is closing. 408 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP); 409 return FALSE; // Exit and return FALSE 410 } 411 } 412 } 413 414 if (fullscreen) { // Are we still in fullscreen mode 415 416 /* 417 * If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 418 * which force a top level window down to the taskbar once our window is visible. 419 * For the window style we'll create a WS_POPUP window. 420 * This type of window has no border around it, making it perfect for fullscreen mode. 421 422 * Finally, we disable the mouse pointer. If your program is not interactive, 423 * it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though. 424 */ 425 dwExStyle = WS_EX_APPWINDOW; // Window extended style 426 dwStyle = WS_POPUP; // Window style 427 ShowCursor(FALSE); // Hide mosue pointer 428 } 429 else { 430 431 /* 432 * If we're using a window instead of fullscreen mode, 433 * we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 434 * For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 435 * WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 436 * window menu, and minimize / maximize buttons. 437 */ 438 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style 439 dwStyle = WS_OVERLAPPEDWINDOW; // Window style 440 } 441 442 /* 443 * By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 444 * instead, the window will be made larger to account for the pixels needed to draw the window border. 445 * In fullscreen mode, this command has no effect. 446 */ 447 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust window to true resqusted 448 449 /* 450 * WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 451 * These styles prevent other windows from drawing over or into our OpenGL Window. 452 */ 453 if (!(hWnd = CreateWindowEx(dwExStyle, // Extended style for the window 454 "OpenGL", // Class name 455 title, // Window title 456 WS_CLIPSIBLINGS | // Requried window style 457 WS_CLIPCHILDREN | // Requried window style 458 dwStyle, // Select window style 459 0, 0, // Window position 460 WindowRect.right - WindowRect.left, // Calculate adjusted window width 461 WindowRect.bottom - WindowRect.top, // Calculate adjusted window height 462 NULL, // No parent window 463 NULL, // No menu 464 hInstance, // Instance 465 NULL))) // Don't pass anything to WM_CREATE 466 { 467 KillGLWindow(); //Reset the display 468 MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 469 return FALSE; // Retrurn FALSE; 470 } 471 472 /* 473 * aside from the stencil buffer and the (slow) accumulation buffer 474 */ 475 static PIXELFORMATDESCRIPTOR pfd = // pfd tells windows how we want things to be 476 { 477 sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 478 1, // Version number 479 PFD_DRAW_TO_WINDOW | // Format must support window 480 PFD_SUPPORT_OPENGL | // Format must support OpenGL 481 PFD_DOUBLEBUFFER, // Must support double buffer 482 PFD_TYPE_RGBA, // Request an RGBA format 483 bits, // Select our color depth 484 0, 0, 0, 0, 0, 0, // Color bits ignored 485 0, // No alpha buffer 486 0, // shift bit ignored 487 0, // No accumulation buffer 488 0, 0, 0, 0, // Accumulation bits ignored 489 16, // 16Bits Z_Buffer (depth buffer) 490 0, // No stencil buffer 491 0, // No auxiliary buffer 492 PFD_MAIN_PLANE, // Main drawing layer 493 0, // Reserved 494 0, 0, 0 // Layer makes ignored 495 }; 496 497 if (!(hDC = GetDC(hWnd))) { // Did we get a device context 498 KillGLWindow(); // Reset the display 499 MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 500 return FALSE; // Return FALSE 501 } 502 503 if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { // Did window find a matching pixel format 504 KillGLWindow(); // Reset the display 505 MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 506 return FALSE; // Return FALSE; 507 } 508 509 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { // Are we able to set the pixel format 510 KillGLWindow(); // Reset the display 511 MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 512 return FALSE; // Return FALSE; 513 } 514 515 if (!(hRC = wglCreateContext(hDC))) { // Are we able to rendering context 516 KillGLWindow(); // Reset the display 517 MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 518 return FALSE; // Return FASLE; 519 } 520 521 if (!wglMakeCurrent(hDC, hRC)) { // Try to activate the rendering context 522 KillGLWindow(); // Reset the display 523 MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 524 return FALSE; // Return FALSE 525 } 526 527 /* 528 * ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen. 529 */ 530 ShowWindow(hWnd, SW_SHOW); // Show the window 531 SetForegroundWindow(hWnd); // slightly higher priority 532 SetFocus(hWnd); // Sets keyboard focus to the window 533 ReSizeGLScene(width, height); // Set up our perspective GL screen 534 535 /* 536 * we can set up lighting, textures, and anything else that needs to be setup in InitGL(). 537 */ 538 if (!InitGL()) { // Initialize our newly created GL window 539 KillGLWindow(); // Reset the display 540 MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 541 return FALSE; // Return FALSE 542 } 543 return TRUE; 544 } 545 546 LRESULT CALLBACK WndProc(HWND hWnd, // Handle for this window 547 UINT uMsg, // Message for this window 548 WPARAM wParam, // Additional message information 549 LPARAM lParam) // Additional message information 550 { 551 switch (uMsg) { // Check for window message 552 case WM_ACTIVATE: { // Check minimization state 553 if (!HIWORD(wParam)) { 554 active = TRUE; // Program is active 555 } 556 else { 557 active = FALSE; // Program is no longer active 558 } 559 return 0; // Return to the message loop 560 } 561 case WM_SYSCOMMAND: { // Intercept system commands 562 switch (wParam) { // Check system calls 563 case SC_SCREENSAVE: // Screensaver trying to start 564 case SC_MONITORPOWER: // Monitor trying to enter powersave 565 return 0; // Prevent form happening 566 } 567 break; // Exit 568 } 569 case WM_CLOSE: { // Did we receive a close message 570 PostQuitMessage(0); // Send a quit message 571 return 0; 572 } 573 case WM_KEYDOWN: { // Is a key being held down 574 keys[wParam] = TRUE; // if so, mark it as TRUE 575 return 0; // Jump back 576 } 577 case WM_KEYUP: { // Has a key been released 578 keys[wParam] = FALSE; // if so, mark it as FALSE 579 return 0; // Jump back 580 } 581 case WM_SIZE: { // Resize the OpenGL window 582 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord = width HiWord = height 583 return 0; // Jump back 584 } 585 } 586 return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass all unhandled message to DefWindwProc 587 } 588 589 int WINAPI WinMain(HINSTANCE hInstance, // Instance 590 HINSTANCE hPrevInstance, // Previous instance 591 LPSTR lpCmdLine, // Command line parameters 592 int nCmdShow) // Window show state 593 { 594 MSG msg; // Window message structure 595 BOOL done = FALSE; // Bool variable to exit loop 596 // Ask the user which screen mode they prefer 597 if (MessageBox(NULL, "Would you like to run in fullscreen mode?", 598 "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) 599 { 600 fullscreen = FALSE; // Window mode 601 } 602 // Create our OpenGL window 603 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { // (Modified) 604 return 0; // Quit if window was not create 605 } 606 607 while (!done) { // Loop that runs until donw = TRUE 608 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Is there a message wating 609 if (msg.message == WM_QUIT) { // Havw we received a quit message 610 done = TRUE; // if so done = TRUE 611 } 612 else { // If not, deal with window message 613 TranslateMessage(&msg); // Translate message 614 DispatchMessage(&msg); // Dispatch message 615 } 616 } 617 else { 618 // Draw the scene. Watch for ESC key and quit message from DrawGLScene() 619 if (active) { // Program active 620 if (keys[VK_ESCAPE]) { // Was ESC pressed 621 done = TRUE; // ESC signalled a quit 622 } 623 else { // Not time to quit, update screen 624 DrawGLScene(); // Draw scene 625 SwapBuffers(hDC); // Swap buffers (double buffering) 626 } 627 } 628 /******************************************************************************************************************************************/ 629 /******************************************************************************************************************************************/ 630 /******************************************************************************************************************************************/ 631 /******************************************************************************************************************************************/ 632 /* 633 * It allows us to press the F1 key to switch from fullscreen mode to 634 * windowed mode or windowed mode to fullscreen mode. 635 */ 636 if (keys[VK_F1]) { // Is F1 being pressed 637 keys[VK_F1] = FALSE; // If so make key FASLE 638 KillGLWindow(); // Kill our current window 639 fullscreen = !fullscreen; // Toggle fullscreen / window mode 640 //Recreate our OpenGL window(modified) 641 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { 642 return 0; // Quit if window was not create 643 } 644 } 645 } 646 } 647 // Shutdown 648 KillGLWindow(); // Kill the window 649 return (msg.wParam); // Exit the program 650 }
Thanks for Nehe's tutorials, this is his home.