outdated: 7.Texture Filters, Lighting & Keyboard Control
这一篇主要是对键盘和灯光的控制。
up、down、right和left控制图形的旋转方向。L控制灯光的开关,F控制灯光模糊化程度。小键盘的+和-控制图形接近屏幕还是远离屏幕。在程序的最后会有演示。
代码如下,修改部分位于双行星号内:
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 BOOL light; // Lighting ON/OFF 30 BOOL lp; // L pressed 31 BOOL fp; // P pressed 32 33 GLfloat xrot; // X rotation 34 GLfloat yrot; // Y rotation 35 GLfloat xspeed; // X rotation speed 36 GLfloat yspeed; // Y rotation speed 37 GLfloat z = -5.0f; // Depth into the screen 38 39 GLuint texture[3]; // Storage for one texture 40 41 GLfloat LightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; // Ambient light values 42 43 GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // Diffuse light values 44 45 GLfloat LightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f}; // Light position 46 47 GLuint filter; 48 /******************************************************************************************************************************************/ 49 /******************************************************************************************************************************************/ 50 51 52 /* 53 * CreateGLWindow() has a reference to WndProc() but WndProc() comes after CreateGLWindow(). 54 */ 55 56 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc 57 58 /* 59 * The job of the next section of code is to resize the OpenGL scene 60 * whenever the window (assuming you are using a Window rather than fullscreen mode) has been resized. 61 */ 62 63 AUX_RGBImageRec* LoadBMP(char* Filename) // Loads a bitmap image 64 { 65 FILE* File = NULL; // File handle 66 67 if (!Filename) { // Make sure a filename was given 68 return NULL; // If not return NULL 69 } 70 71 File = fopen(Filename, "r"); // Check to see of the file exists 72 if (File) { 73 fclose(File); 74 return auxDIBImageLoad(Filename); // Load the bitmap and return a pointer 75 } 76 77 return NULL; 78 } 79 /******************************************************************************************************************************************/ 80 /******************************************************************************************************************************************/ 81 int LoadGLTextures() // Load bitmap and convert to texture 82 { 83 int Status = FALSE; // Status indicator 84 85 AUX_RGBImageRec* TextureImage[1]; // Create storage space for the texture 86 87 memset(TextureImage, 0, sizeof(void*)*1); // Set the pointer to NULL 88 89 // Load the bitmap, check for error, if bitmap's not found quit 90 if (TextureImage[0] = LoadBMP("1.bmp")) { 91 Status = TRUE; 92 93 glGenTextures(3, &texture[0]); // Create the texture 94 95 // Typical texture Generation using data from the bitmap 96 glBindTexture(GL_TEXTURE_2D, texture[0]); 97 // Generate the texture 98 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 99 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 100 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, 101 GL_UNSIGNED_BYTE, TextureImage[0]->data); 102 103 glBindTexture(GL_TEXTURE_2D, texture[1]); 104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear filtering 105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear filtering 106 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, 107 GL_UNSIGNED_BYTE, TextureImage[0]->data); 108 109 glBindTexture(GL_TEXTURE_2D, texture[2]); 110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); 112 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, GL_RGB, 113 GL_UNSIGNED_BYTE, TextureImage[0]->data); 114 } 115 116 if (TextureImage[0]) { 117 if (TextureImage[0]->data) { 118 free(TextureImage[0]->data); 119 } 120 free(TextureImage[0]); 121 } 122 return Status; 123 } 124 /******************************************************************************************************************************************/ 125 /******************************************************************************************************************************************/ 126 127 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize and initialize the GL window 128 { 129 if (height == 0) { // Prevent a divide by zero by 130 height = 1; // Making height equal one 131 } 132 133 glViewport(0, 0, width, height); // Reset the current viewport 134 135 /* 136 * The following lines set the screen up for a perspective view. 137 * Meaning things in the distance get smaller. This creates a realistic looking scene. 138 * The perspective is calculated with a 45 degree viewing angle based on 139 * the windows width and height. The 0.1f, 100.0f is the starting point and 140 * ending point for how deep we can draw into the screen. 141 * 142 * The projection matrix is responsible for adding perspective to our scene. 143 * glLoadIdentity() restores the selected matrix to it's original state. 144 * The modelview matrix is where our object information is stored. 145 * Lastly we reset the modelview matrix. 146 */ 147 148 glMatrixMode(GL_PROJECTION); // Select the projection matrix 149 glLoadIdentity(); // Reset the projection matrix 150 151 // Calculate the aspect ratio of the window 152 gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 153 154 glMatrixMode(GL_MODELVIEW); // Seclet the modelview matrix 155 glLoadIdentity(); // Reset the modelview matrix 156 } 157 /******************************************************************************************************************************************/ 158 /******************************************************************************************************************************************/ 159 int InitGL(GLvoid) // All setup for OpenGL goes here 160 { 161 if (!LoadGLTextures()) { // Jump to texture loading routine 162 return FALSE; // If texture didn't load return false 163 } 164 glEnable(GL_TEXTURE_2D); // Enable texture mapping 165 /* 166 * Smooth shading blends colors nicely across a polygon, and smoothes out lighting. 167 */ 168 169 glShadeModel(GL_SMOOTH); // Enables smooth shading 170 171 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black background 172 173 /* 174 * Think of the depth buffer as layers into the screen. 175 * The depth buffer keeps track of how deep objects are into the screen. 176 */ 177 178 glClearDepth(1.0f); // Depth buffer setup 179 glEnable(GL_DEPTH_TEST); // Enable depth testing 180 glDepthFunc(GL_LEQUAL); // The typr of depth test to do 181 182 /* 183 * Next we tell OpenGL we want the best perspective correction to be done. 184 * This causes a very tiny performance hit, but makes the perspective view look a bit better. 185 */ 186 187 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really nice perspective calculations 188 189 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup the ambient light 190 191 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup the diffuse light 192 193 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Steup the position light 194 195 glEnable(GL_LIGHT1); // Enable light one 196 return TRUE; 197 } 198 /* 199 * For now all we will do is clear the screen to the color we previously decided on, 200 * clear the depth buffer and reset the scene. We wont draw anything yet. 201 */ 202 int DrawGLScene(GLvoid) // Here's where we do all the drawing 203 { 204 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and the depth buffer 205 glLoadIdentity(); // Reset the current modelview matrix 206 207 /* 208 * When you do a glLoadIdentity() what you are doing is moving back to 209 * the center of the screen with the X axis(轴) running left to right, 210 * the Y axis moving up and down, and the Z axis moving into, and out of the screen. 211 */ 212 /* 213 * glTranslatef(x, y, z) moves along the X, Y and Z axis, in that order. 214 * When you translate, you are not moving a set amount from the center of the screen, 215 * you are moving a set amount from wherever you currently were on the screen. 216 */ 217 glTranslatef(0.0f, 0.0f, z); // Move into the screen 5 units 218 glRotatef(xrot, 1.0f, 0.0f, 0.0f); 219 glRotatef(yrot, 0.0f, 1.0f, 0.0f); 220 221 glBindTexture(GL_TEXTURE_2D, texture[filter]); // Select a texture baseds on filter 222 223 /* 224 * By drawing in a clockwise order, the square will be drawn as a back face. 225 * Meaning the side of the quad we see is actually the back. 226 * Objects drawn in a counter clockwise order will be facing us. 227 */ 228 229 glBegin(GL_QUADS); // Draw a quad 230 // Front Face 231 glNormal3f(0.0f, 0.0f, 1.0f); 232 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 233 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 234 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad 235 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad 236 // Back Face 237 glNormal3f(0.0f, 0.0f, -1.0f); 238 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad 239 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 240 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 241 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad 242 // Top Face 243 glNormal3f(0.0f, 1.0f, 0.0f); 244 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 245 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad 246 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad 247 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 248 // Bottom Face 249 glNormal3f(0.0f, -1.0f, 0.0f); 250 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad 251 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad 252 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 253 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 254 // Right face 255 glNormal3f(1.0f, 0.0f, 0.0f); 256 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad 257 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 258 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad 259 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 260 // Left Face 261 glNormal3f(-1.0f, 0.0f, 0.0f); 262 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad 263 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 264 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad 265 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 266 glEnd(); // Done drawing the quad 267 268 xrot += xspeed; 269 yrot += yspeed; 270 return TRUE; // everthing went OK 271 } 272 /******************************************************************************************************************************************/ 273 /******************************************************************************************************************************************/ 274 /* 275 * The job of KillGLWindow() is to release the Rendering Context, 276 * the Device Context and finally the Window Handle. 277 */ 278 279 GLvoid KillGLWindow(GLvoid) // Properly kill the window 280 { 281 if (fullscreen) { // Are we in fullscreen mode 282 283 /* 284 * We use ChangeDisplaySettings(NULL,0) to return us to our original desktop. 285 * After we've switched back to the desktop we make the cursor visible again. 286 */ 287 288 ChangeDisplaySettings(NULL, 0); // if so switch back to the desktop 289 ShowCursor(TRUE); // Show mouse pointer 290 } 291 292 if (hRC) { // Do we have a rendering context 293 if (!wglMakeCurrent(NULL, NULL)) { // Are we able to release the DC and RC contexts 294 MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 295 } 296 297 if (!wglDeleteContext(hRC)) { // Are we able to delete the RC 298 MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 299 hRC = NULL; // Set RC to NULL 300 } 301 302 if (hDC && !ReleaseDC(hWnd, hDC)) { // Are we able to release the DC 303 MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 304 hDC = NULL; // Set DC to NULL 305 } 306 if (hWnd && !DestroyWindow(hWnd)) { // Are we able to destroy the window 307 MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 308 hWnd = NULL; // Set hWnd to NULL 309 } 310 311 if (!UnregisterClass("OpenGL", hInstance)) { // Are we able to unregister class 312 MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 313 hInstance = NULL; // Set hInstance to NULL 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 * It allows us to press the F1 key to switch from fullscreen mode to 631 * windowed mode or windowed mode to fullscreen mode. 632 */ 633 /******************************************************************************************************************************************/ 634 /******************************************************************************************************************************************/ 635 if (keys['L'] && !lp) { // L key being pressed not held 636 lp = TRUE; // lp become TRUE 637 light = !light; // Toggle light TRUE/FALSE 638 639 if (!light) { 640 glDisable(GL_LIGHTING); // Disable light 641 } 642 else { 643 glEnable(GL_LIGHTING); // Enable light 644 } 645 } 646 647 if (!keys['L']) { 648 lp = FALSE; 649 } 650 if (keys['F'] && !fp) { 651 fp = TRUE; 652 filter += 1; 653 if (filter > 2) { 654 filter = 0; 655 } 656 } 657 if (!keys['F']) { 658 fp = FALSE; 659 } 660 if (keys[VK_SUBTRACT]) { //VK_PRIOR 661 z -= 0.005f; 662 } 663 if (keys[VK_ADD]) { // VK_NEXT 664 z += 0.005f; 665 } 666 if (keys[VK_UP]) { 667 xspeed -= 0.0005f; 668 } 669 if (keys[VK_DOWN]) { 670 xspeed += 0.0005f; 671 } 672 if (keys[VK_RIGHT]) { 673 yspeed += 0.0005f; 674 } 675 if (keys[VK_LEFT]) { 676 yspeed -= 0.0005f; 677 } 678 if (keys[VK_F1]) { // Is F1 being pressed 679 keys[VK_F1] = FALSE; // If so make key FASLE 680 KillGLWindow(); // Kill our current window 681 fullscreen = !fullscreen; // Toggle fullscreen / window mode 682 //Recreate our OpenGL window(modified) 683 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { 684 return 0; // Quit if window was not create 685 } 686 } 687 } 688 } 689 /******************************************************************************************************************************************/ 690 /******************************************************************************************************************************************/ 691 // Shutdown 692 KillGLWindow(); // Kill the window 693 return (msg.wParam); // Exit the program 694 }
Thanks for Nehe's tutorials, this is his home.
对于vc++中对应的VK键。如下:
VK_LBUTTON |
1 |
鼠标左键 |
VK_RBUTTON |
2 |
鼠标右键 |
VK_CANCEL |
3 |
Cancel |
VK_MBUTTON |
4 |
鼠标中键 |
VK_XBUTTON1 |
5 |
X1鼠标按钮 |
VK_XBUTTON2 |
6 |
X2鼠标按钮 |
VK_BACK |
8 |
Backspace |
VK_TAB |
9 |
Tab |
VK_CLEAR |
12 |
Clear |
VK_RETURN |
13 |
Enter |
VK_SHIFT |
16 |
Shift |
VK_CONTROL |
17 |
Ctrl |
VK_MENU |
18 |
Alt |
VK_PAUSE |
19 |
Pause |
VK_CAPITAL |
20 |
Caps Lock |
VK_KANA |
21 |
IME假名模式 |
VK_HANGUL |
21 |
IME Hanguel模式 |
VK_JUNJA |
23 |
IME Junja模式 |
VK_FINAL |
24 |
|
VK_HANJA |
25 |
|
VK_KANJI |
25* |
|
VK_ESCAPE |
27 |
Esc |
VK_CONVERT |
28 |
|
VK_NONCONVERT |
29 |
|
VK_ACCEPT |
30 |
|
VK_MODECHANGE |
31 |
|
VK_SPACE |
32 |
Space |
VK_PRIOR |
33 |
Page Up |
VK_NEXT |
34 |
Page Down |
VK_END |
35 |
End |
VK_HOME |
36 |
Home |
VK_LEFT |
37 |
Left Arrow |
VK_UP |
38 |
Up Arrow |
VK_RIGHT |
39 |
Right Arrow |
VK_DOWN |
40 |
Down Arrow |
VK_SELECT |
41 |
Select |
VK_PRINT |
42 |
|
VK_EXECUTE |
43 |
Execute |
VK_SNAPSHOT |
44 |
Snapshot |
VK_INSERT |
45 |
Insert |
VK_DELETE |
46 |
Delete |
VK_HELP |
47 |
Help |
|
48 |
0 |
|
49 |
1 |
|
50 |
2 |
|
51 |
3 |
|
52 |
4 |
|
53 |
5 |
|
54 |
6 |
|
55 |
7 |
|
56 |
8 |
|
57 |
9 |
|
65 |
A |
|
66 |
B |
|
67 |
C |
|
68 |
D |
|
69 |
E |
|
70 |
F |
|
71 |
G |
|
72 |
H |
|
73 |
I |
|
74 |
J |
|
75 |
K |
|
76 |
L |
|
77 |
M |
|
78 |
N |
|
79 |
O |
|
80 |
P |
|
81 |
Q |
|
82 |
R |
|
83 |
S |
|
84 |
T |
|
85 |
U |
|
86 |
V |
|
87 |
W |
|
88 |
X |
|
89 |
Y |
|
90 |
Z |
VK_LWIN |
91 |
|
VK_RWIN |
92 |
|
VK_APPS |
93 |
|
VK_SLEEP |
95 |
|
VK_NUMPAD0 |
96 |
小键盘 0 |
VK_NUMPAD1 |
97 |
小键盘 1 |
VK_NUMPAD2 |
98 |
小键盘 2 |
VK_NUMPAD3 |
99 |
小键盘 3 |
VK_NUMPAD4 |
100 |
小键盘 4 |
VK_NUMPAD5 |
101 |
小键盘 5 |
VK_NUMPAD6 |
102 |
小键盘 6 |
VK_NUMPAD7 |
103 |
小键盘 7 |
VK_NUMPAD8 |
104 |
小键盘 8 |
VK_NUMPAD9 |
105 |
小键盘 9 |
VK_MULTIPLY |
106 |
小键盘 * |
VK_ADD |
107 |
小键盘 + |
VK_SEPARATOR |
108 |
小键盘 Enter |
VK_SUBTRACT |
109 |
小键盘 - |
VK_DECIMAL |
110 |
小键盘 . |
VK_DIVIDE |
111 |
小键盘 / |
VK_F1 |
112 |
F1 |
VK_F2 |
113 |
F2 |
VK_F3 |
114 |
F3 |
VK_F4 |
115 |
F4 |
VK_F5 |
116 |
F5 |
VK_F6 |
117 |
F6 |
VK_F7 |
118 |
F7 |
VK_F8 |
119 |
F8 |
VK_F9 |
120 |
F9 |
VK_F10 |
121 |
F10 |
VK_F11 |
122 |
F11 |
VK_F12 |
123 |
F12 |
VK_F13 |
124 |
|
VK_F14 |
125 |
|
VK_F15 |
126 |
|
VK_F16 |
127 |
|
VK_F17 |
128 |
|
VK_F18 |
129 |
|
VK_F19 |
130 |
|
VK_F20 |
131 |
|
VK_F21 |
132 |
|
VK_F22 |
133 |
|
VK_F23 |
134 |
|
VK_F24 |
135 |
|
VK_NUMLOCK |
144 |
Num Lock |
VK_SCROLL |
145 |
Scroll |
VK_LSHIFT |
160 |
|
VK_RSHIFT |
161 |
|
VK_LCONTROL |
162 |
|
VK_RCONTROL |
163 |
|
VK_LMENU |
164 |
|
VK_RMENU |
165 |
|
VK_BROWSER_BACK |
166 |
|
VK_BROWSER_FORWARD |
167 |
|
VK_BROWSER_REFRESH |
168 |
|
VK_BROWSER_STOP |
169 |
|
VK_BROWSER_SEARCH |
170 |
|
VK_BROWSER_FAVORITES |
171 |
|
VK_BROWSER_HOME |
172 |
|
VK_VOLUME_MUTE |
173 |
VolumeMute |
VK_VOLUME_DOWN |
174 |
VolumeDown |
VK_VOLUME_UP |
175 |
VolumeUp |
VK_MEDIA_NEXT_TRACK |
176 |
|
VK_MEDIA_PREV_TRACK |
177 |
|
VK_MEDIA_STOP |
178 |
|
VK_MEDIA_PLAY_PAUSE |
179 |
|
VK_LAUNCH_MAIL |
180 |
|
VK_LAUNCH_MEDIA_SELECT |
181 |
|
VK_LAUNCH_APP1 |
182 |
|
VK_LAUNCH_APP2 |
183 |
|
VK_OEM_1 |
186 |
; : |
VK_OEM_PLUS |
187 |
= + |
VK_OEM_COMMA |
188 |
|
VK_OEM_MINUS |
189 |
- _ |
VK_OEM_PERIOD |
190 |
|
VK_OEM_2 |
191 |
/ ? |
VK_OEM_3 |
192 |
` ~ |
VK_OEM_4 |
219 |
[ { |
VK_OEM_5 |
220 |
\ | |
VK_OEM_6 |
221 |
] } |
VK_OEM_7 |
222 |
' " |
VK_OEM_8 |
223 |
|
VK_OEM_102 |
226 |
|
VK_PACKET |
231 |
|
VK_PROCESSKEY |
229 |
|
VK_ATTN |
246 |
|
VK_CRSEL |
247 |
|
VK_EXSEL |
248 |
|
VK_EREOF |
249 |
|
VK_PLAY |
250 |
|
VK_ZOOM |
251 |
|
VK_NONAME |
252 |
|
VK_PA1 |
253 |
|
VK_OEM_CLEAR |
254 |