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