outdated: 24.Tokens, Extensions, Scissor Testing And TGA Loading
这一篇主要说的是,怎样实现在窗口中裁剪一个小的视图窗口(即glScissor()函数)?以及对glGetString()函数的应用。
在本文中,用到的贴图材质是TGA格式图片,相对于JPG格式,会更加清晰,因使用不失真的压缩。不了解TGA格式图片的可以看看这篇。基于对TGA格式的了解,具有独有的一个8位的Alpha通道。在其代码中,在24位和32位之间来转换,差的8位即为Alpha。所以,一开始会有一个变量type,默认为32位---GL_RGBA。支持扩展是很好的一个特性,使得DrawGLScene()函数中的glGetString()函数可以使用。
LoadTGA()函数中,只会加载24位和32位的TGA,首先第一个变量,
GLubyte TGAheader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
在与所读文件前12个字节比较后,确保是Targa文件。
下一个变量,
GLubyte header[6];
读取宽(位置)、高(位置)和每像素值的比特位,共6字节。
glPrint函数中的glScalef()函数用来设置字体的形变。
DrawGLScene()函数中的glGetString()函数,其参数有四个,依次为渲染器,渲染器出处,渲染器版本,支持的扩展。
Meaning | |
---|---|
|
Returns the company responsible for this OpenGL implementation. This name does not change from release to release. |
|
Returns the name of the renderer. This name is typically specific to a particular configuration of a hardware platform. It does not change from release to release. |
|
Returns a version or release number. |
|
Returns a space-separated list of supported extensions to OpenGL. |
glScissor()函数,设置一个小窗口,当然都是在windows窗体的限制内。
void WINAPI glScissor( GLint x, GLint y, GLsizei width, GLsizei height );
下面为代码,同样修改部分位于双行星号内。
1 #include <windows.h> 2 #include <stdarg.h> 3 #include <stdio.h> 4 #include <math.h> 5 #include <string.h> 6 #include <gl/glew.h> 7 #include <gl/glut.h> 8 #include <GL/GLUAX.H> 9 #include <GL/glext.h> 10 #pragma comment(lib, "legacy_stdio_definitions.lib") 11 12 /* 13 * Every OpenGL program is linked to a Rendering Context. 14 * A Rendering Context is what links OpenGL calls to the Device Context. 15 * In order for your program to draw to a Window you need to create a Device Context. 16 * The DC connects the Window to the GDI (Graphics Device Interface). 17 */ 18 19 HGLRC hRC = NULL; // Permanent rendering context 20 HDC hDC = NULL; // Private GDI device context 21 HWND hWnd = NULL; // Holds our window handle 22 HINSTANCE hInstance; // Holds the instance of the application 23 24 /* 25 * It's important to make this global so that each procedure knows if 26 * the program is running in fullscreen mode or not. 27 */ 28 29 bool keys[256]; // Array used for the keyboard routine 30 bool active = TRUE; // Window active flag set to TRUE by default 31 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default 32 /******************************************************************************************************************************************/ 33 /******************************************************************************************************************************************/ 34 int scroll; // Used for scrolling the screen 35 int maxtokens; // Keeps track of the number of extensions supported 36 int swidth; // Scissor width 37 int sheight; // Scissor height 38 39 GLuint base; // Base display list for the font 40 41 typedef struct { 42 GLubyte* imageData; 43 GLuint bpp; // Image color depth in bits per pixel 44 GLuint width; 45 GLuint height; 46 GLuint texID; // Texture ID used to select a texture 47 } TextureImage; 48 49 TextureImage texture[1]; 50 51 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc 52 53 bool LoadTGA(TextureImage* texture, char* filename) // Loads a TGA filr into memory 54 { 55 GLubyte TGAheader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Uncompressed TGA 56 GLubyte TGAcompare[12]; // Used to compare TGA header 57 GLubyte header[6]; // First 6 useful bytes from the header 58 GLuint bytesPerpixel; // Holds number of byte per pixel used in the TGA file 59 60 GLuint imageSize; // Used to store the image size when setting aside ram 61 GLuint temp; // Temporary variable 62 GLuint type = GL_RGBA; // Set the default GL mode to RGBA (32 bpp) 63 64 FILE* file = fopen(filename, "rb"); 65 66 if ((file == NULL) || // Dose file even exits 67 (fread(TGAcompare, 1, sizeof(TGAcompare), file) != sizeof(TGAcompare)) || // Are there 12 bytes to read 68 (memcmp(TGAheader, TGAcompare, sizeof(TGAheader)) != 0) || // Dose the header match what we want 69 (fread(header, 1, sizeof(header), file) != sizeof(header))) // If so read next 6 header bytes 70 { 71 if (file == NULL) { 72 return false; 73 } 74 else { 75 fclose(file); 76 return false; 77 } 78 } 79 texture->width = header[1] * 256 + header[0]; // Determine the TGA width (highbyte * 256 + lowbyte) 80 texture->height = header[3] * 256 + header[2]; // Determine the TGA height (highbyte * 256 + lowbyte) 81 82 if (texture->width <= 0 || texture->height <= 0 || (header[4] != 24 && header[4] != 32)) { 83 fclose(file); 84 return false; 85 } 86 87 texture->bpp = header[4]; // Grab the TGA's bits per pixel (24 or 32) 88 bytesPerpixel = texture->bpp / 8; // Divide by 8 to get the bytes per pixel 89 // Calculate the memory required for the TGA data 90 imageSize = texture->width * texture->height * bytesPerpixel; 91 92 texture->imageData = (GLubyte*)malloc(imageSize); // Resever memory to hold the TGA data 93 94 if (texture->imageData == NULL || 95 fread(texture->imageData, 1, imageSize, file) != imageSize) 96 { 97 if (texture->imageData == NULL) { 98 free(texture->imageData); 99 } 100 fclose(file); 101 return false; 102 } 103 104 for (GLuint i = 0; i < int(imageSize); i += bytesPerpixel) { 105 temp = texture->imageData[i]; // Swap the 1st and 3rd bytes (R and B) 106 texture->imageData[i] = texture->imageData[i + 2]; 107 texture->imageData[i + 2] = temp; 108 } 109 fclose(file); 110 111 // Build a texture from the data 112 glGenTextures(1, &texture[0].texID); 113 114 glBindTexture(GL_TEXTURE_2D, texture[0].texID); 115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 117 118 // The TGA was 24 bit, the type will be GL_RGB, the TGA was 32 bit, the type would be GL_RGBA 119 if (texture[0].bpp == 24) { 120 type = GL_RGB; 121 } 122 123 glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, 124 GL_UNSIGNED_BYTE, texture[0].imageData); 125 return true; 126 } 127 128 GLvoid BuildFont(GLvoid) 129 { 130 base = glGenLists(256); 131 glBindTexture(GL_TEXTURE_2D, texture[0].texID); 132 133 for (int loop = 0; loop < 256; ++loop) { 134 float cx = float(loop % 16) / 16.0f; // X position of current character 135 float cy = float(loop / 16) / 16.0f; // Y position of current character 136 glNewList(base + loop, GL_COMPILE); 137 glBegin(GL_QUADS); 138 glTexCoord2f(cx, 1.0f - cy - 0.0625f); // Texture coord 139 glVertex2d(0, 16); // Vertex coord 140 glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.0625f); 141 glVertex2i(16, 16); 142 glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.001f); 143 glVertex2i(16, 0); 144 glTexCoord2f(cx, 1.0f - cy - 0.001f); 145 glVertex2i(0, 0); 146 glEnd(); 147 glTranslated(14, 0, 0); 148 glEndList(); 149 } 150 } 151 152 GLvoid KillFont(GLvoid) 153 { 154 glDeleteLists(base, 256); 155 } 156 157 GLvoid glPrint(GLint x, GLint y, int set, const char* fmt, ...) 158 { 159 char text[1024]; 160 va_list ap; // Pointer to list of arguments 161 162 if (fmt == NULL) { 163 return; 164 } 165 166 va_start(ap, fmt); // Parses the string for variables 167 vsprintf(text, fmt, ap); // And converts symbols to actual 168 va_end(ap); // Result are stored in text 169 170 if (set > 1) { 171 set = 1; 172 } 173 glEnable(GL_TEXTURE_2D); 174 glLoadIdentity(); 175 glTranslated(x, y, 0); 176 glListBase(base - 32 + (128 * set)); // Choose the font set (0 or 1) 177 178 glScalef(1.0f, 2.0f, 1.0f); // Make the text 2X taller 179 180 glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Write the text to the screen 181 182 glDisable(GL_TEXTURE_2D); 183 } 184 185 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize and initialize the GL window 186 { 187 swidth = width; // Set scissor width to window width 188 sheight = height; 189 190 if (height == 0) { // Prevent a divide by zero by 191 height = 1; // Making height equal one 192 } 193 194 glViewport(0, 0, width, height); // Reset the current viewport 195 196 /* 197 * The following lines set the screen up for a perspective view. 198 * Meaning things in the distance get smaller. This creates a realistic looking scene. 199 * The perspective is calculated with a 45 degree viewing angle based on 200 * the windows width and height. The 0.1f, 100.0f is the starting point and 201 * ending point for how deep we can draw into the screen. 202 * 203 * The projection matrix is responsible for adding perspective to our scene. 204 * glLoadIdentity() restores the selected matrix to it's original state. 205 * The modelview matrix is where our object information is stored. 206 * Lastly we reset the modelview matrix. 207 */ 208 209 glMatrixMode(GL_PROJECTION); // Select the projection matrix 210 glLoadIdentity(); // Reset the projection matrix 211 212 // Calculate the aspect ratio of the window 213 // gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 214 glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f); // Create orhto 640X480 view (0, 0, at the top) 215 216 glMatrixMode(GL_MODELVIEW); // Seclet the modelview matrix 217 glLoadIdentity(); // Reset the modelview matrix 218 } 219 220 int InitGL(GLvoid) // All setup for OpenGL goes here 221 { 222 if (!LoadTGA(&texture[0], "Font.tga")) { 223 return FALSE; 224 } 225 226 BuildFont(); 227 228 glShadeModel(GL_SMOOTH); // Enables smooth shading 229 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black background 230 231 glClearDepth(1.0f); // Depth buffer setup 232 233 glBindTexture(GL_TEXTURE_2D, texture[0].texID); 234 235 return TRUE; 236 } 237 /* 238 * For now all we will do is clear the screen to the color we previously decided on, 239 * clear the depth buffer and reset the scene. We wont draw anything yet. 240 */ 241 int DrawGLScene(GLvoid) // Here's where we do all the drawing 242 { 243 char* token; // Storage for our token 244 int cnt = 0; // Loacl counter variable 245 246 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 247 248 glColor3f(1.0f, 0.5f, 0.5f); 249 glPrint(50, 16, 1, "Renderer"); 250 glPrint(80, 48, 1, "Vendor"); 251 glPrint(66, 80, 1, "Version"); 252 253 glColor3f(1.0f, 0.7f, 0.4f); 254 glPrint(200, 16, 1, (char*)glGetString(GL_RENDERER)); 255 glPrint(200, 48, 1, (char*)glGetString(GL_VENDOR)); 256 glPrint(200, 80, 1, (char*)glGetString(GL_VERSION)); 257 258 glColor3f(0.5f, 0.5f, 1.0f); 259 glPrint(250, 432, 1, "OpenGl"); 260 261 glLoadIdentity(); 262 glColor3f(1.0f, 1.0f, 1.0f); 263 glBegin(GL_LINE_STRIP); 264 glVertex2d(639, 417); 265 glVertex2d(0, 417); 266 glVertex2d(0, 480); 267 glVertex2d(639, 480); 268 glVertex2d(639, 128); 269 glEnd(); 270 glBegin(GL_LINE_STRIP); 271 glVertex2d(0, 128); 272 glVertex2d(639, 128); 273 glVertex2d(639, 1); 274 glVertex2d(0, 1); 275 glVertex2d(0, 417); 276 glEnd(); 277 278 glScissor(1, int(0.135416f * sheight), swidth - 2, int(0.597916f * sheight)); // Define scissor region 279 glEnable(GL_SCISSOR_TEST); 280 // Allocate memory for our extension string 281 char* text = (char*)malloc(strlen((char*)glGetString(GL_EXTENSIONS)) + 1); 282 strcpy(text, (char*)glGetString(GL_EXTENSIONS)); // Grab the extension list, store in text 283 284 token = strtok(text, " "); 285 while (token != NULL) { 286 cnt++; 287 if (cnt > maxtokens) { 288 maxtokens = cnt; 289 } 290 291 glColor3f(0.5f, 1.0f, 0.5f); 292 glPrint(0, 96 + (cnt * 32) - scroll, 0, "%i", cnt); // Print the current extension number 293 294 glColor3f(1.0f, 1.0f, 0.5f); 295 glPrint(50, 96 + (cnt * 32) - scroll, 0, token); // Print the current token extension name 296 297 token = strtok(NULL, " "); // Serch for the next token 298 } 299 300 glDisable(GL_SCISSOR_TEST); 301 free(text); 302 303 glFlush(); 304 return true; 305 } 306 /******************************************************************************************************************************************/ 307 /******************************************************************************************************************************************/ 308 /* 309 * The job of KillGLWindow() is to release the Rendering Context, 310 * the Device Context and finally the Window Handle. 311 */ 312 313 GLvoid KillGLWindow(GLvoid) // Properly kill the window 314 { 315 if (fullscreen) { // Are we in fullscreen mode 316 317 /* 318 * We use ChangeDisplaySettings(NULL,0) to return us to our original desktop. 319 * After we've switched back to the desktop we make the cursor visible again. 320 */ 321 322 ChangeDisplaySettings(NULL, 0); // if so switch back to the desktop 323 ShowCursor(TRUE); // Show mouse pointer 324 } 325 326 if (hRC) { // Do we have a rendering context 327 if (!wglMakeCurrent(NULL, NULL)) { // Are we able to release the DC and RC contexts 328 MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 329 } 330 331 if (!wglDeleteContext(hRC)) { // Are we able to delete the RC 332 MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 333 hRC = NULL; // Set RC to NULL 334 } 335 336 if (hDC && !ReleaseDC(hWnd, hDC)) { // Are we able to release the DC 337 MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 338 hDC = NULL; // Set DC to NULL 339 } 340 if (hWnd && !DestroyWindow(hWnd)) { // Are we able to destroy the window 341 MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 342 hWnd = NULL; // Set hWnd to NULL 343 } 344 345 if (!UnregisterClass("OpenGL", hInstance)) { // Are we able to unregister class 346 MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 347 hInstance = NULL; // Set hInstance to NULL 348 } 349 } 350 /******************************************************************************************************************************************/ 351 /******************************************************************************************************************************************/ 352 KillFont(); 353 /******************************************************************************************************************************************/ 354 /******************************************************************************************************************************************/ 355 } 356 357 /* 358 * The next section of code creates our OpenGL Window. 359 */ 360 361 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) 362 { 363 /* 364 * Find a pixel format that matches the one we want 365 */ 366 GLuint PixelFormat; // Holds the result after serching for a match 367 368 /* 369 * Before you create a window, you MUST register a Class for the window 370 */ 371 WNDCLASS wc; // Windows class structure 372 373 /* 374 * dwExStyle and dwStyle will store the Extended and normal Window Style Information. 375 */ 376 DWORD dwExStyle; // Window extend style 377 DWORD dwStyle; // Window style 378 379 RECT WindowRect; // Grabs rectangle upper left/lower right values 380 WindowRect.left = (long)0; // Set left value to 0 381 WindowRect.right = (long)width; // Set right value to requested width 382 WindowRect.top = (long)0; // Set top value to 0 383 WindowRect.bottom = (long)height; // Set bottom value to requested height 384 385 fullscreen = fullscreenflag; // Set the global fullscreen flag 386 387 /* 388 * The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 389 * CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 390 * WndProc is the procedure that watches for messages in our program. 391 * No extra Window data is used so we zero the two fields. Then we set the instance. 392 * Next we set hIcon to NULL meaning we don't want an ICON in the Window, 393 * and for a mouse pointer we use the standard arrow. The background color doesn't matter 394 * (we set that in GL). We don't want a menu in this Window so we set it to NULL, 395 * and the class name can be any name you want. I'll use "OpenGL" for simplicity. 396 */ 397 hInstance = GetModuleHandle(NULL); // Grab an instance for our window 398 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on move, and own DC for window 399 wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc handles message 400 wc.cbClsExtra = 0; // No extra window date 401 wc.cbWndExtra = 0; // No extra window date 402 wc.hInstance = hInstance; // set the instance 403 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load the default icon 404 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer 405 wc.hbrBackground = NULL; // No background requried for GL 406 wc.lpszMenuName = NULL; // We don't want a menu 407 wc.lpszClassName = "OpenGL"; // set the class name 408 409 if (!RegisterClass(&wc)) { // Attempt to register the window class 410 MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 411 return FALSE; // Exit and return false 412 } 413 414 if (fullscreen) { // attempt fullsreen model 415 416 /* 417 T* here are a few very important things you should keep in mind when switching to full screen mode. 418 * Make sure the width and height that you use in fullscreen mode is the same as 419 * the width and height you plan to use for your window, and most importantly, 420 * set fullscreen mode BEFORE you create your window. 421 */ 422 DEVMODE dmScreenSettings; // Device mode 423 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared 424 dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size of devmode structure 425 dmScreenSettings.dmPelsWidth = width; // Select window width 426 dmScreenSettings.dmPelsHeight = height; // Select window height 427 dmScreenSettings.dmBitsPerPel = bits; // Select bits per pixel 428 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 429 430 /* 431 * In the line below ChangeDisplaySettings tries to switch to a mode that matches 432 * what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 433 * because it's supposed to remove the start bar at the bottom of the screen, 434 * plus it doesn't move or resize the windows on your desktop when you switch to 435 * fullscreen mode and back. 436 */ 437 //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar 438 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { 439 //If the mode fails, offer two options. Quit or run in a window 440 if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use" 441 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) 442 { 443 fullscreen = FALSE; // Select windowed mode (fullscreen=FLASE) 444 } 445 else { 446 // Pop up a message box letting user know the programe is closing. 447 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP); 448 return FALSE; // Exit and return FALSE 449 } 450 } 451 } 452 453 if (fullscreen) { // Are we still in fullscreen mode 454 455 /* 456 * If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 457 * which force a top level window down to the taskbar once our window is visible. 458 * For the window style we'll create a WS_POPUP window. 459 * This type of window has no border around it, making it perfect for fullscreen mode. 460 461 * Finally, we disable the mouse pointer. If your program is not interactive, 462 * it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though. 463 */ 464 dwExStyle = WS_EX_APPWINDOW; // Window extended style 465 dwStyle = WS_POPUP; // Window style 466 ShowCursor(FALSE); // Hide mosue pointer 467 } 468 else { 469 470 /* 471 * If we're using a window instead of fullscreen mode, 472 * we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 473 * For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 474 * WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 475 * window menu, and minimize / maximize buttons. 476 */ 477 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style 478 dwStyle = WS_OVERLAPPEDWINDOW; // Window style 479 } 480 481 /* 482 * By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 483 * instead, the window will be made larger to account for the pixels needed to draw the window border. 484 * In fullscreen mode, this command has no effect. 485 */ 486 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust window to true resqusted 487 488 /* 489 * WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 490 * These styles prevent other windows from drawing over or into our OpenGL Window. 491 */ 492 if (!(hWnd = CreateWindowEx(dwExStyle, // Extended style for the window 493 "OpenGL", // Class name 494 title, // Window title 495 WS_CLIPSIBLINGS | // Requried window style 496 WS_CLIPCHILDREN | // Requried window style 497 dwStyle, // Select window style 498 0, 0, // Window position 499 WindowRect.right - WindowRect.left, // Calculate adjusted window width 500 WindowRect.bottom - WindowRect.top, // Calculate adjusted window height 501 NULL, // No parent window 502 NULL, // No menu 503 hInstance, // Instance 504 NULL))) // Don't pass anything to WM_CREATE 505 { 506 KillGLWindow(); //Reset the display 507 MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 508 return FALSE; // Retrurn FALSE; 509 } 510 511 /* 512 * aside from the stencil buffer and the (slow) accumulation buffer 513 */ 514 static PIXELFORMATDESCRIPTOR pfd = // pfd tells windows how we want things to be 515 { 516 sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 517 1, // Version number 518 PFD_DRAW_TO_WINDOW | // Format must support window 519 PFD_SUPPORT_OPENGL | // Format must support OpenGL 520 PFD_DOUBLEBUFFER, // Must support double buffer 521 PFD_TYPE_RGBA, // Request an RGBA format 522 bits, // Select our color depth 523 0, 0, 0, 0, 0, 0, // Color bits ignored 524 0, // No alpha buffer 525 0, // shift bit ignored 526 0, // No accumulation buffer 527 0, 0, 0, 0, // Accumulation bits ignored 528 16, // 16Bits Z_Buffer (depth buffer) 529 0, // No stencil buffer 530 0, // No auxiliary buffer 531 PFD_MAIN_PLANE, // Main drawing layer 532 0, // Reserved 533 0, 0, 0 // Layer makes ignored 534 }; 535 536 if (!(hDC = GetDC(hWnd))) { // Did we get a device context 537 KillGLWindow(); // Reset the display 538 MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 539 return FALSE; // Return FALSE 540 } 541 542 if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { // Did window find a matching pixel format 543 KillGLWindow(); // Reset the display 544 MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 545 return FALSE; // Return FALSE; 546 } 547 548 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { // Are we able to set the pixel format 549 KillGLWindow(); // Reset the display 550 MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 551 return FALSE; // Return FALSE; 552 } 553 554 if (!(hRC = wglCreateContext(hDC))) { // Are we able to rendering context 555 KillGLWindow(); // Reset the display 556 MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 557 return FALSE; // Return FASLE; 558 } 559 560 if (!wglMakeCurrent(hDC, hRC)) { // Try to activate the rendering context 561 KillGLWindow(); // Reset the display 562 MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 563 return FALSE; // Return FALSE 564 } 565 566 /* 567 * ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen. 568 */ 569 ShowWindow(hWnd, SW_SHOW); // Show the window 570 SetForegroundWindow(hWnd); // slightly higher priority 571 SetFocus(hWnd); // Sets keyboard focus to the window 572 ReSizeGLScene(width, height); // Set up our perspective GL screen 573 574 /* 575 * we can set up lighting, textures, and anything else that needs to be setup in InitGL(). 576 */ 577 if (!InitGL()) { // Initialize our newly created GL window 578 KillGLWindow(); // Reset the display 579 MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 580 return FALSE; // Return FALSE 581 } 582 return TRUE; 583 } 584 585 LRESULT CALLBACK WndProc(HWND hWnd, // Handle for this window 586 UINT uMsg, // Message for this window 587 WPARAM wParam, // Additional message information 588 LPARAM lParam) // Additional message information 589 { 590 switch (uMsg) { // Check for window message 591 case WM_ACTIVATE: { // Check minimization state 592 if (!HIWORD(wParam)) { 593 active = TRUE; // Program is active 594 } 595 else { 596 active = FALSE; // Program is no longer active 597 } 598 return 0; // Return to the message loop 599 } 600 case WM_SYSCOMMAND: { // Intercept system commands 601 switch (wParam) { // Check system calls 602 case SC_SCREENSAVE: // Screensaver trying to start 603 case SC_MONITORPOWER: // Monitor trying to enter powersave 604 return 0; // Prevent form happening 605 } 606 break; // Exit 607 } 608 case WM_CLOSE: { // Did we receive a close message 609 PostQuitMessage(0); // Send a quit message 610 return 0; 611 } 612 case WM_KEYDOWN: { // Is a key being held down 613 keys[wParam] = TRUE; // if so, mark it as TRUE 614 return 0; // Jump back 615 } 616 case WM_KEYUP: { // Has a key been released 617 keys[wParam] = FALSE; // if so, mark it as FALSE 618 return 0; // Jump back 619 } 620 case WM_SIZE: { // Resize the OpenGL window 621 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord = width HiWord = height 622 return 0; // Jump back 623 } 624 } 625 return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass all unhandled message to DefWindwProc 626 } 627 628 int WINAPI WinMain(HINSTANCE hInstance, // Instance 629 HINSTANCE hPrevInstance, // Previous instance 630 LPSTR lpCmdLine, // Command line parameters 631 int nCmdShow) // Window show state 632 { 633 MSG msg; // Window message structure 634 BOOL done = FALSE; // Bool variable to exit loop 635 // Ask the user which screen mode they prefer 636 if (MessageBox(NULL, "Would you like to run in fullscreen mode?", 637 "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) 638 { 639 fullscreen = FALSE; // Window mode 640 } 641 // Create our OpenGL window 642 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { // (Modified) 643 return 0; // Quit if window was not create 644 } 645 /******************************************************************************************************************************************/ 646 /******************************************************************************************************************************************/ 647 648 while (!done) { // Loop that runs until donw = TRUE 649 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Is there a message wating 650 if (msg.message == WM_QUIT) { // Havw we received a quit message 651 done = TRUE; // if so done = TRUE 652 } 653 else { // If not, deal with window message 654 TranslateMessage(&msg); // Translate message 655 DispatchMessage(&msg); // Dispatch message 656 } 657 } 658 else { 659 // Draw the scene. Watch for ESC key and quit message from DrawGLScene() 660 if (active) { // Program active 661 if (keys[VK_ESCAPE]) { // Was ESC pressed 662 done = TRUE; // ESC signalled a quit 663 } 664 else { // Not time to quit, update screen 665 DrawGLScene(); // Draw scene 666 SwapBuffers(hDC); // Swap buffers (double buffering) 667 } 668 } 669 670 if (keys[VK_UP] && (scroll > 0)) { 671 scroll -= 2; 672 } 673 if (keys[VK_DOWN] && (scroll < 32 * (maxtokens - 9))) { 674 scroll += 2; 675 } 676 /* 677 * It allows us to press the F1 key to switch from fullscreen mode to 678 * windowed mode or windowed mode to fullscreen mode. 679 */ 680 if (keys[VK_F1]) { // Is F1 being pressed 681 keys[VK_F1] = FALSE; // If so make key FASLE 682 KillGLWindow(); // Kill our current window 683 fullscreen = !fullscreen; // Toggle fullscreen / window mode 684 //Recreate our OpenGL window(modified) 685 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { 686 return 0; // Quit if window was not create 687 } 688 } 689 } 690 } 691 // Shutdown 692 KillGLWindow(); // Kill the window 693 return (msg.wParam); // Exit the program 694 } 695 /******************************************************************************************************************************************/ 696 /******************************************************************************************************************************************/
Thanks for Nehe's tutorials, this is his home.