标签:
大多数人认为GL_RGBA中的alpha通道是透明与不透明程度的,即0为完全透明,1为不透明。
The Blending equation:(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
s和d为下标,指定的是资源和目标像素。S和D是混合因子,可以表示怎样混合像素。S为(As,As,As,As)(AKA source alpha)而D为(1,1,1,1)-(As,As,As,As)(AKA one minus src alpha)。
即方程式又可表示为:(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bd (1 - As), As As + Ad (1 - As))
在OpenGL中正确绘制混合色彩的方式是在绘制其余部分后,再来绘制所有透明部分的多边形(alpha<1.0)。
首先应该绘制反向的多边形(背面的),使用透明功能时应关闭深度测试功能。
修改部分位于双行星号内。
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 blend; // Blend ON/OFF (new) 31 BOOL lp; // L pressed 32 BOOL fp; // P pressed 33 BOOL bp; // B pressed (new) 34 GLfloat xrot; // X rotation 35 GLfloat yrot; // Y rotation 36 GLfloat xspeed; // X rotation speed 37 GLfloat yspeed; // Y rotation speed 38 GLfloat z = -5.0f; // Depth into the screen 39 40 GLuint texture[3]; // Storage for one texture 41 42 GLfloat LightAmbient[] = {0.5f, 0.5f, 0.5f, 1.0f}; // Ambient light values 43 44 GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // Diffuse light values 45 46 GLfloat LightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f}; // Light position 47 48 GLuint filter; 49 /******************************************************************************************************************************************/ 50 /******************************************************************************************************************************************/ 51 52 53 /* 54 * CreateGLWindow() has a reference to WndProc() but WndProc() comes after CreateGLWindow(). 55 */ 56 57 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc 58 59 /* 60 * The job of the next section of code is to resize the OpenGL scene 61 * whenever the window (assuming you are using a Window rather than fullscreen mode) has been resized. 62 */ 63 64 AUX_RGBImageRec* LoadBMP(char* Filename) // Loads a bitmap image 65 { 66 FILE* File = NULL; // File handle 67 68 if (!Filename) { // Make sure a filename was given 69 return NULL; // If not return NULL 70 } 71 72 File = fopen(Filename, "r"); // Check to see of the file exists 73 if (File) { 74 fclose(File); 75 return auxDIBImageLoad(Filename); // Load the bitmap and return a pointer 76 } 77 78 return NULL; 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 GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize and initialize the GL window 126 { 127 if (height == 0) { // Prevent a divide by zero by 128 height = 1; // Making height equal one 129 } 130 131 glViewport(0, 0, width, height); // Reset the current viewport 132 133 /* 134 * The following lines set the screen up for a perspective view. 135 * Meaning things in the distance get smaller. This creates a realistic looking scene. 136 * The perspective is calculated with a 45 degree viewing angle based on 137 * the windows width and height. The 0.1f, 100.0f is the starting point and 138 * ending point for how deep we can draw into the screen. 139 * 140 * The projection matrix is responsible for adding perspective to our scene. 141 * glLoadIdentity() restores the selected matrix to it‘s original state. 142 * The modelview matrix is where our object information is stored. 143 * Lastly we reset the modelview matrix. 144 */ 145 146 glMatrixMode(GL_PROJECTION); // Select the projection matrix 147 glLoadIdentity(); // Reset the projection matrix 148 149 // Calculate the aspect ratio of the window 150 gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 151 152 glMatrixMode(GL_MODELVIEW); // Seclet the modelview matrix 153 glLoadIdentity(); // Reset the modelview matrix 154 } 155 156 int InitGL(GLvoid) // All setup for OpenGL goes here 157 { 158 if (!LoadGLTextures()) { // Jump to texture loading routine 159 return FALSE; // If texture didn‘t load return false 160 } 161 glEnable(GL_TEXTURE_2D); // Enable texture mapping 162 /* 163 * Smooth shading blends colors nicely across a polygon, and smoothes out lighting. 164 */ 165 166 glShadeModel(GL_SMOOTH); // Enables smooth shading 167 168 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black background 169 /******************************************************************************************************************************************/ 170 /******************************************************************************************************************************************/ 171 glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Full brightness, 50% alpha (new) 172 // Blending function for translucency based on source alpha value (new) 173 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 174 /******************************************************************************************************************************************/ 175 /******************************************************************************************************************************************/ 176 /* 177 * Think of the depth buffer as layers into the screen. 178 * The depth buffer keeps track of how deep objects are into the screen. 179 */ 180 181 glClearDepth(1.0f); // Depth buffer setup 182 glEnable(GL_DEPTH_TEST); // Enable depth testing 183 glDepthFunc(GL_LEQUAL); // The typr of depth test to do 184 185 /* 186 * Next we tell OpenGL we want the best perspective correction to be done. 187 * This causes a very tiny performance hit, but makes the perspective view look a bit better. 188 */ 189 190 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really nice perspective calculations 191 192 glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup the ambient light 193 194 glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup the diffuse light 195 196 glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Steup the position light 197 198 glEnable(GL_LIGHT1); // Enable light one 199 return TRUE; 200 } 201 /* 202 * For now all we will do is clear the screen to the color we previously decided on, 203 * clear the depth buffer and reset the scene. We wont draw anything yet. 204 */ 205 int DrawGLScene(GLvoid) // Here‘s where we do all the drawing 206 { 207 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the screen and the depth buffer 208 glLoadIdentity(); // Reset the current modelview matrix 209 210 /* 211 * When you do a glLoadIdentity() what you are doing is moving back to 212 * the center of the screen with the X axis(轴) running left to right, 213 * the Y axis moving up and down, and the Z axis moving into, and out of the screen. 214 */ 215 /* 216 * glTranslatef(x, y, z) moves along the X, Y and Z axis, in that order. 217 * When you translate, you are not moving a set amount from the center of the screen, 218 * you are moving a set amount from wherever you currently were on the screen. 219 */ 220 glTranslatef(0.0f, 0.0f, z); // Move into the screen 5 units 221 glRotatef(xrot, 1.0f, 0.0f, 0.0f); 222 glRotatef(yrot, 0.0f, 1.0f, 0.0f); 223 224 glBindTexture(GL_TEXTURE_2D, texture[filter]); // Select a texture baseds on filter 225 226 /* 227 * By drawing in a clockwise order, the square will be drawn as a back face. 228 * Meaning the side of the quad we see is actually the back. 229 * Objects drawn in a counter clockwise order will be facing us. 230 */ 231 232 glBegin(GL_QUADS); // Draw a quad 233 // Front Face 234 glNormal3f(0.0f, 0.0f, 1.0f); 235 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 236 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 237 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad 238 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad 239 // Back Face 240 glNormal3f(0.0f, 0.0f, -1.0f); 241 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad 242 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 243 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 244 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad 245 // Top Face 246 glNormal3f(0.0f, 1.0f, 0.0f); 247 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 248 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad 249 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad 250 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 251 // Bottom Face 252 glNormal3f(0.0f, -1.0f, 0.0f); 253 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad 254 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad 255 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 256 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 257 // Right face 258 glNormal3f(1.0f, 0.0f, 0.0f); 259 glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad 260 glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad 261 glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad 262 glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad 263 // Left Face 264 glNormal3f(-1.0f, 0.0f, 0.0f); 265 glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad 266 glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad 267 glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad 268 glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad 269 glEnd(); // Done drawing the quad 270 271 xrot += xspeed; 272 yrot += yspeed; 273 return TRUE; // everthing went OK 274 } 275 /* 276 * The job of KillGLWindow() is to release the Rendering Context, 277 * the Device Context and finally the Window Handle. 278 */ 279 280 GLvoid KillGLWindow(GLvoid) // Properly kill the window 281 { 282 if (fullscreen) { // Are we in fullscreen mode 283 284 /* 285 * We use ChangeDisplaySettings(NULL,0) to return us to our original desktop. 286 * After we‘ve switched back to the desktop we make the cursor visible again. 287 */ 288 289 ChangeDisplaySettings(NULL, 0); // if so switch back to the desktop 290 ShowCursor(TRUE); // Show mouse pointer 291 } 292 293 if (hRC) { // Do we have a rendering context 294 if (!wglMakeCurrent(NULL, NULL)) { // Are we able to release the DC and RC contexts 295 MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 296 } 297 298 if (!wglDeleteContext(hRC)) { // Are we able to delete the RC 299 MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 300 hRC = NULL; // Set RC to NULL 301 } 302 303 if (hDC && !ReleaseDC(hWnd, hDC)) { // Are we able to release the DC 304 MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 305 hDC = NULL; // Set DC to NULL 306 } 307 if (hWnd && !DestroyWindow(hWnd)) { // Are we able to destroy the window 308 MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 309 hWnd = NULL; // Set hWnd to NULL 310 } 311 312 if (!UnregisterClass("OpenGL", hInstance)) { // Are we able to unregister class 313 MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION); 314 hInstance = NULL; // Set hInstance to NULL 315 } 316 } 317 } 318 319 /* 320 * The next section of code creates our OpenGL Window. 321 */ 322 323 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) 324 { 325 /* 326 * Find a pixel format that matches the one we want 327 */ 328 GLuint PixelFormat; // Holds the result after serching for a match 329 330 /* 331 * Before you create a window, you MUST register a Class for the window 332 */ 333 WNDCLASS wc; // Windows class structure 334 335 /* 336 * dwExStyle and dwStyle will store the Extended and normal Window Style Information. 337 */ 338 DWORD dwExStyle; // Window extend style 339 DWORD dwStyle; // Window style 340 341 RECT WindowRect; // Grabs rectangle upper left/lower right values 342 WindowRect.left = (long)0; // Set left value to 0 343 WindowRect.right = (long)width; // Set right value to requested width 344 WindowRect.top = (long)0; // Set top value to 0 345 WindowRect.bottom = (long)height; // Set bottom value to requested height 346 347 fullscreen = fullscreenflag; // Set the global fullscreen flag 348 349 /* 350 * The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 351 * CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 352 * WndProc is the procedure that watches for messages in our program. 353 * No extra Window data is used so we zero the two fields. Then we set the instance. 354 * Next we set hIcon to NULL meaning we don‘t want an ICON in the Window, 355 * and for a mouse pointer we use the standard arrow. The background color doesn‘t matter 356 * (we set that in GL). We don‘t want a menu in this Window so we set it to NULL, 357 * and the class name can be any name you want. I‘ll use "OpenGL" for simplicity. 358 */ 359 hInstance = GetModuleHandle(NULL); // Grab an instance for our window 360 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on move, and own DC for window 361 wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc handles message 362 wc.cbClsExtra = 0; // No extra window date 363 wc.cbWndExtra = 0; // No extra window date 364 wc.hInstance = hInstance; // set the instance 365 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load the default icon 366 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load the arrow pointer 367 wc.hbrBackground = NULL; // No background requried for GL 368 wc.lpszMenuName = NULL; // We don‘t want a menu 369 wc.lpszClassName = "OpenGL"; // set the class name 370 371 if (!RegisterClass(&wc)) { // Attempt to register the window class 372 MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 373 return FALSE; // Exit and return false 374 } 375 376 if (fullscreen) { // attempt fullsreen model 377 378 /* 379 T* here are a few very important things you should keep in mind when switching to full screen mode. 380 * Make sure the width and height that you use in fullscreen mode is the same as 381 * the width and height you plan to use for your window, and most importantly, 382 * set fullscreen mode BEFORE you create your window. 383 */ 384 DEVMODE dmScreenSettings; // Device mode 385 memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory‘s cleared 386 dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size of devmode structure 387 dmScreenSettings.dmPelsWidth = width; // Select window width 388 dmScreenSettings.dmPelsHeight = height; // Select window height 389 dmScreenSettings.dmBitsPerPel = bits; // Select bits per pixel 390 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 391 392 /* 393 * In the line below ChangeDisplaySettings tries to switch to a mode that matches 394 * what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 395 * because it‘s supposed to remove the start bar at the bottom of the screen, 396 * plus it doesn‘t move or resize the windows on your desktop when you switch to 397 * fullscreen mode and back. 398 */ 399 //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar 400 if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { 401 //If the mode fails, offer two options. Quit or run in a window 402 if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use" 403 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES) 404 { 405 fullscreen = FALSE; // Select windowed mode (fullscreen=FLASE) 406 } 407 else { 408 // Pop up a message box letting user know the programe is closing. 409 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP); 410 return FALSE; // Exit and return FALSE 411 } 412 } 413 } 414 415 if (fullscreen) { // Are we still in fullscreen mode 416 417 /* 418 * If we are still in fullscreen mode we‘ll set the extended style to WS_EX_APPWINDOW, 419 * which force a top level window down to the taskbar once our window is visible. 420 * For the window style we‘ll create a WS_POPUP window. 421 * This type of window has no border around it, making it perfect for fullscreen mode. 422 423 * Finally, we disable the mouse pointer. If your program is not interactive, 424 * it‘s usually nice to disable the mouse pointer when in fullscreen mode. It‘s up to you though. 425 */ 426 dwExStyle = WS_EX_APPWINDOW; // Window extended style 427 dwStyle = WS_POPUP; // Window style 428 ShowCursor(FALSE); // Hide mosue pointer 429 } 430 else { 431 432 /* 433 * If we‘re using a window instead of fullscreen mode, 434 * we‘ll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 435 * For style we‘ll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 436 * WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 437 * window menu, and minimize / maximize buttons. 438 */ 439 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window extended style 440 dwStyle = WS_OVERLAPPEDWINDOW; // Window style 441 } 442 443 /* 444 * By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 445 * instead, the window will be made larger to account for the pixels needed to draw the window border. 446 * In fullscreen mode, this command has no effect. 447 */ 448 AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust window to true resqusted 449 450 /* 451 * WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 452 * These styles prevent other windows from drawing over or into our OpenGL Window. 453 */ 454 if (!(hWnd = CreateWindowEx(dwExStyle, // Extended style for the window 455 "OpenGL", // Class name 456 title, // Window title 457 WS_CLIPSIBLINGS | // Requried window style 458 WS_CLIPCHILDREN | // Requried window style 459 dwStyle, // Select window style 460 0, 0, // Window position 461 WindowRect.right - WindowRect.left, // Calculate adjusted window width 462 WindowRect.bottom - WindowRect.top, // Calculate adjusted window height 463 NULL, // No parent window 464 NULL, // No menu 465 hInstance, // Instance 466 NULL))) // Don‘t pass anything to WM_CREATE 467 { 468 KillGLWindow(); //Reset the display 469 MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 470 return FALSE; // Retrurn FALSE; 471 } 472 473 /* 474 * aside from the stencil buffer and the (slow) accumulation buffer 475 */ 476 static PIXELFORMATDESCRIPTOR pfd = // pfd tells windows how we want things to be 477 { 478 sizeof(PIXELFORMATDESCRIPTOR), // Size of this pixel format descriptor 479 1, // Version number 480 PFD_DRAW_TO_WINDOW | // Format must support window 481 PFD_SUPPORT_OPENGL | // Format must support OpenGL 482 PFD_DOUBLEBUFFER, // Must support double buffer 483 PFD_TYPE_RGBA, // Request an RGBA format 484 bits, // Select our color depth 485 0, 0, 0, 0, 0, 0, // Color bits ignored 486 0, // No alpha buffer 487 0, // shift bit ignored 488 0, // No accumulation buffer 489 0, 0, 0, 0, // Accumulation bits ignored 490 16, // 16Bits Z_Buffer (depth buffer) 491 0, // No stencil buffer 492 0, // No auxiliary buffer 493 PFD_MAIN_PLANE, // Main drawing layer 494 0, // Reserved 495 0, 0, 0 // Layer makes ignored 496 }; 497 498 if (!(hDC = GetDC(hWnd))) { // Did we get a device context 499 KillGLWindow(); // Reset the display 500 MessageBox(NULL, "Can‘t create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 501 return FALSE; // Return FALSE 502 } 503 504 if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) { // Did window find a matching pixel format 505 KillGLWindow(); // Reset the display 506 MessageBox(NULL, "Can‘t find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 507 return FALSE; // Return FALSE; 508 } 509 510 if (!SetPixelFormat(hDC, PixelFormat, &pfd)) { // Are we able to set the pixel format 511 KillGLWindow(); // Reset the display 512 MessageBox(NULL, "Can‘t set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 513 return FALSE; // Return FALSE; 514 } 515 516 if (!(hRC = wglCreateContext(hDC))) { // Are we able to rendering context 517 KillGLWindow(); // Reset the display 518 MessageBox(NULL, "Can‘t create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 519 return FALSE; // Return FASLE; 520 } 521 522 if (!wglMakeCurrent(hDC, hRC)) { // Try to activate the rendering context 523 KillGLWindow(); // Reset the display 524 MessageBox(NULL, "Can‘t activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 525 return FALSE; // Return FALSE 526 } 527 528 /* 529 * ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen. 530 */ 531 ShowWindow(hWnd, SW_SHOW); // Show the window 532 SetForegroundWindow(hWnd); // slightly higher priority 533 SetFocus(hWnd); // Sets keyboard focus to the window 534 ReSizeGLScene(width, height); // Set up our perspective GL screen 535 536 /* 537 * we can set up lighting, textures, and anything else that needs to be setup in InitGL(). 538 */ 539 if (!InitGL()) { // Initialize our newly created GL window 540 KillGLWindow(); // Reset the display 541 MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION); 542 return FALSE; // Return FALSE 543 } 544 return TRUE; 545 } 546 547 LRESULT CALLBACK WndProc(HWND hWnd, // Handle for this window 548 UINT uMsg, // Message for this window 549 WPARAM wParam, // Additional message information 550 LPARAM lParam) // Additional message information 551 { 552 switch (uMsg) { // Check for window message 553 case WM_ACTIVATE: { // Check minimization state 554 if (!HIWORD(wParam)) { 555 active = TRUE; // Program is active 556 } 557 else { 558 active = FALSE; // Program is no longer active 559 } 560 return 0; // Return to the message loop 561 } 562 case WM_SYSCOMMAND: { // Intercept system commands 563 switch (wParam) { // Check system calls 564 case SC_SCREENSAVE: // Screensaver trying to start 565 case SC_MONITORPOWER: // Monitor trying to enter powersave 566 return 0; // Prevent form happening 567 } 568 break; // Exit 569 } 570 case WM_CLOSE: { // Did we receive a close message 571 PostQuitMessage(0); // Send a quit message 572 return 0; 573 } 574 case WM_KEYDOWN: { // Is a key being held down 575 keys[wParam] = TRUE; // if so, mark it as TRUE 576 return 0; // Jump back 577 } 578 case WM_KEYUP: { // Has a key been released 579 keys[wParam] = FALSE; // if so, mark it as FALSE 580 return 0; // Jump back 581 } 582 case WM_SIZE: { // Resize the OpenGL window 583 ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord = width HiWord = height 584 return 0; // Jump back 585 } 586 } 587 return DefWindowProc(hWnd, uMsg, wParam, lParam); // Pass all unhandled message to DefWindwProc 588 } 589 590 int WINAPI WinMain(HINSTANCE hInstance, // Instance 591 HINSTANCE hPrevInstance, // Previous instance 592 LPSTR lpCmdLine, // Command line parameters 593 int nCmdShow) // Window show state 594 { 595 MSG msg; // Window message structure 596 BOOL done = FALSE; // Bool variable to exit loop 597 // Ask the user which screen mode they prefer 598 if (MessageBox(NULL, "Would you like to run in fullscreen mode?", 599 "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO) 600 { 601 fullscreen = FALSE; // Window mode 602 } 603 // Create our OpenGL window 604 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { // (Modified) 605 return 0; // Quit if window was not create 606 } 607 608 while (!done) { // Loop that runs until donw = TRUE 609 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Is there a message wating 610 if (msg.message == WM_QUIT) { // Havw we received a quit message 611 done = TRUE; // if so done = TRUE 612 } 613 else { // If not, deal with window message 614 TranslateMessage(&msg); // Translate message 615 DispatchMessage(&msg); // Dispatch message 616 } 617 } 618 else { 619 // Draw the scene. Watch for ESC key and quit message from DrawGLScene() 620 if (active) { // Program active 621 if (keys[VK_ESCAPE]) { // Was ESC pressed 622 done = TRUE; // ESC signalled a quit 623 } 624 else { // Not time to quit, update screen 625 DrawGLScene(); // Draw scene 626 SwapBuffers(hDC); // Swap buffers (double buffering) 627 } 628 } 629 630 /* 631 * It allows us to press the F1 key to switch from fullscreen mode to 632 * windowed mode or windowed mode to fullscreen mode. 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 /******************************************************************************************************************************************/ 679 /******************************************************************************************************************************************/ 680 if (keys[‘B‘] && !bp) { // new 681 bp = TRUE; 682 blend = !blend; 683 if (blend) { 684 glEnable(GL_BLEND); 685 glDisable(GL_DEPTH_TEST); 686 } 687 else { 688 glDisable(GL_BLEND); 689 glEnable(GL_DEPTH_TEST); 690 } 691 } 692 if (keys[‘B‘]) { 693 bp = FALSE; 694 } 695 /******************************************************************************************************************************************/ 696 /******************************************************************************************************************************************/ 697 if (keys[VK_F1]) { // Is F1 being pressed 698 keys[VK_F1] = FALSE; // If so make key FASLE 699 KillGLWindow(); // Kill our current window 700 fullscreen = !fullscreen; // Toggle fullscreen / window mode 701 //Recreate our OpenGL window(modified) 702 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) { 703 return 0; // Quit if window was not create 704 } 705 } 706 } 707 } 708 // Shutdown 709 KillGLWindow(); // Kill the window 710 return (msg.wParam); // Exit the program 711 }
Thanks for Nehe‘s tutorials, this is his home.
标签:
原文地址:http://www.cnblogs.com/clairvoyant/p/5642403.html