outdated: 8.Blending

大多数人认为GL_RGBA中的alpha通道是透明与不透明程度的,即0为完全透明,1为不透明。

The Blending equation:(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)

sd为下标,指定的是资源和目标像素。SD是混合因子,可以表示怎样混合像素。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)。

首先应该绘制反向的多边形(背面的),使用透明功能时应关闭深度测试功能。

B控制透明效果的开启。

修改部分位于双行星号内。

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
 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 }
main.cpp

Thanks for Nehe's tutorials, this is his home.

原文地址:https://www.cnblogs.com/clairvoyant/p/5642403.html