码迷,mamicode.com
首页 > 其他好文 > 详细

outdated: 26.Clipping & Reflections Using The Stencil Buffer

时间:2016-08-01 19:35:45      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

这一章实现了物体在地面上的投影,以及物体表面灯光闪烁的效果。

我在原本的代码上添加了些功能,W/S/A/D和UP/DOWN/LEFT/RIGHT为左右前后移动,实现了小球在地面滚动的效果。

技术分享

物体的投影,其实为在其Y轴的另一个物体相对;

技术分享

物体表面的闪烁效果其实为另一张贴图,两个效果都使用了混合透明效果。

技术分享

在InitGL()函数中,新函数glClearStencil()的作用为清理模板缓存,默认值为0,其参数技术分享,m为模板缓存的比特位。

glTexGeni()函数使用了球面映射算法来生成贴图坐标。原型为:

void WINAPI glTexGeni(
   GLenum coord,
   GLenum pname,
   GLint  param
);

coord为贴图坐标,GL_S, GL_T, GL_R, or GL_Q。

pname为生成贴图坐标函数的符号名,GL_TEXTURE_GEN_MODE, GL_OBJECT_PLANE, or GL_EYE_PLANE。

param为一个特定的参数,GL_OBJECT_LINEAR, GL_EYE_LINEAR, or GL_SPHERE_MAP。

在DrawGLScene()函数中,glColorMask()用来指定在帧缓存区的单个颜色分量是否可以改变,比如红色分量为GL_FALSE,则不论是否进行绘图操作,不会改变帧缓存区任何像素的红色分量。

glStencilFunc()函数设置模板测试的函数和引用值,其第二个参数ref夹在[0, 2n-1],其n为在模板缓存中的bitplanes数目,第三个参数mask为ANDed,以及在测试完成时的the reference value and the stored stencil value。

glStencilOp()函数设置模板的测试操作,其原型:

void WINAPI glStencilOp(
   GLenum fail,
   GLenum zfail,
   GLenum zpass
);

fail参数为当模板测试失败时,包含的符号常量为GL_KEEP,GL_ZERO,GL_REPLACE,GL_INCR,GL_DECR,GL_INVERT。

zfail参数为当模板测试通过,但深度测试失败时,包含和fail参数一样的符号常量。

zpass参数当模板测试和深度测试都通过时,或模板测试通过或不启用深度缓存、深度测试时,包含和fail参数一样的符号常量。

glClipPlane()函数指定一个所有几何体被裁剪的平面,其原型为:

void WINAPI glClipPlane(
   GLenum   plane,
   const GLdouble *equation
);

equation参数为其平面方程,

double eqr[] = { 0.0f, -1.0f, 0.0f, 0.0f };

可以发现其Y轴为负的,无论Y值为负还是Y值在Floor下面,我们将看到物体,若相反则会出现差错。下图为eqr[] = { 0.0f, 1.0f, 0.0f, 0.0f }时,

技术分享

代码如下,同样修改部分位于双行星号内。

  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 /*
  9 *  Every OpenGL program is linked to a Rendering Context.
 10 *  A Rendering Context is what links OpenGL calls to the Device Context.
 11 *  In order for your program to draw to a Window you need to create a Device Context.
 12 *  The DC connects the Window to the GDI (Graphics Device Interface).
 13 */
 14 
 15 HGLRC     hRC = NULL;         // Permanent rendering context
 16 HDC       hDC = NULL;         // Private GDI device context
 17 HWND      hWnd = NULL;        // Holds our window handle
 18 HINSTANCE hInstance;          // Holds the instance of the application
 19 
 20 /*
 21 *  It‘s important to make this global so that each procedure knows if
 22 *  the program is running in fullscreen mode or not.
 23 */
 24 
 25 bool keys[256];         // Array used for the keyboard routine
 26 bool active = TRUE;     // Window active flag set to TRUE by default
 27 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default
 28 /******************************************************************************************************************************************/
 29 /******************************************************************************************************************************************/
 30 // Light parameters
 31 static GLfloat LightAmb[] = { 0.7f, 0.7f, 0.7f, 1.0f };
 32 static GLfloat LightDif[] = { 1.0f, 1.0f, 1.0f, 1.0f };
 33 static GLfloat LightPos[] = { 4.0f, 4.0f, 6.0f, 1.0f };
 34 
 35 GLUquadricObj * q;                // Quadratic for drawing a sphere
 36 
 37 GLfloat xrot = 0.0f;
 38 GLfloat xrotspeed = 0.0f;
 39 GLfloat zrot = 0.0f;
 40 GLfloat zrotspeed = 0.0f;
 41 GLfloat xpos = 0.0f;
 42 GLfloat xposspeed = 0.0f;
 43 GLfloat zpos = -7.0f;             // Depth
 44 GLfloat zposspeed = 0.0f;
 45 GLfloat height = 0.8f;            // Height of ball    from floor
 46 GLfloat heightspeed = 0.0f;
 47 
 48 GLuint texture[3];
 49 
 50 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
 51 
 52 AUX_RGBImageRec* LoadBMP(char* Filename)              // Loads a bitmap image
 53 {
 54     FILE* File = NULL;                                // File handle
 55 
 56     if (!Filename) {                                  // Make sure a filename was given
 57         return NULL;                                  // If not return NULL
 58     }
 59 
 60     File = fopen(Filename, "r");                      // Check to see of the file exists
 61     if (File) {
 62         fclose(File);
 63         return auxDIBImageLoad(Filename);             // Load the bitmap and return a pointer
 64     }
 65 
 66     return NULL;
 67 }
 68 
 69 int LoadGLTextures()
 70 {
 71     int Status = false;
 72     AUX_RGBImageRec* TextureImage[3];
 73     memset(TextureImage, 0, sizeof(void*) * 3);
 74     if ((TextureImage[0] = LoadBMP("EnvWall.bmp")) &&
 75         (TextureImage[1] = LoadBMP("Ball.bmp")) &&
 76         (TextureImage[2] = LoadBMP("EnvRoll.bmp")))
 77     {
 78         Status = true;
 79         glGenTextures(3, &texture[0]);
 80         for (int loop = 0; loop < 3; ++loop) {
 81             glBindTexture(GL_TEXTURE_2D, texture[loop]);
 82             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 83             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 84             glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY,
 85                 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);
 86         }
 87         for (int loop = 0; loop < 3; ++loop) {
 88             if (TextureImage[loop]) {
 89                 if (TextureImage[loop]->data)
 90                     free(TextureImage[loop]->data);
 91                 free(TextureImage[loop]);
 92             }
 93         }
 94     }
 95     return Status;
 96 }
 97 /******************************************************************************************************************************************/
 98 /******************************************************************************************************************************************/
 99 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
100 {
101     if (height == 0) {                                // Prevent a divide by zero by
102         height = 1;                                   // Making height equal one
103     }
104     
105     glViewport(0, 0, width, height);                  // Reset the current viewport
106 
107     /*
108      *  The following lines set the screen up for a perspective view. 
109      *  Meaning things in the distance get smaller. This creates a realistic looking scene. 
110      *  The perspective is calculated with a 45 degree viewing angle based on 
111      *  the windows width and height. The 0.1f, 100.0f is the starting point and 
112      *  ending point for how deep we can draw into the screen.
113      *
114      *  The projection matrix is responsible for adding perspective to our scene.
115      *  glLoadIdentity() restores the selected matrix to it‘s original state.
116      *  The modelview matrix is where our object information is stored.
117      *   Lastly we reset the modelview matrix.
118      */
119 
120     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
121     glLoadIdentity();                                 // Reset the projection matrix
122     
123                                                       // Calculate the aspect ratio of the window
124     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
125 //    glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);  // Create orhto 640X480 view (0, 0, at the top)
126 
127     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
128     glLoadIdentity();                                 // Reset the modelview matrix
129 }
130 /******************************************************************************************************************************************/
131 /******************************************************************************************************************************************/
132 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
133 {
134     if (!LoadGLTextures()) {
135         return false;
136     }
137 
138     glShadeModel(GL_SMOOTH);
139     glClearColor(0.3f, 0.3f, 0.3f, 1.0f);             // Background
140     glClearDepth(1.0f);                               // Depth buffer setup
141     glClearStencil(0);                                // Clear the stencil buffer to 0
142     glEnable(GL_DEPTH_TEST);
143     glDepthFunc(GL_LEQUAL);
144     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
145     glEnable(GL_TEXTURE_2D);
146     
147     glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
148     glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);
149     glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
150 
151     glEnable(GL_LIGHT0);
152     glEnable(GL_LIGHTING);
153 
154     q = gluNewQuadric();
155     gluQuadricNormals(q, GL_SMOOTH);            // Generate smooth Normals for the quad
156     gluQuadricTexture(q, GL_TRUE);              // Enable texture coords for the quad
157     
158     // Use the Sphere Mapping algorithm to generate the texture coordinates
159     glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);     // Set up sphere mapping
160     glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);     // Set up sphere mapping
161 
162     return TRUE;
163 }
164 
165 void DrawObject()
166 {
167     glColor3f(1.0f, 1.0f, 1.0f);
168     glBindTexture(GL_TEXTURE_2D, texture[1]);
169     gluSphere(q, 1.2f, 32, 16);              // Draw first sphere
170 
171     glBindTexture(GL_TEXTURE_2D, texture[2]);
172     glColor4f(1.0f, 1.0f, 1.0f, 0.4f);
173     glEnable(GL_BLEND);
174     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
175 
176     glEnable(GL_TEXTURE_GEN_S);
177     glEnable(GL_TEXTURE_GEN_T);
178 
179     gluSphere(q, 1.2f, 32, 16);              // Draw another sphere
180 
181     glDisable(GL_TEXTURE_GEN_S);
182     glDisable(GL_TEXTURE_GEN_T);
183     glDisable(GL_BLEND);
184 }
185 
186 void DrawFloor()
187 {
188     glBindTexture(GL_TEXTURE_2D, texture[0]);
189     glBegin(GL_QUADS);
190         glNormal3f(0.0f, 1.0f, 0.0f);
191         glTexCoord2f(0.0f, 1.0f);
192         glVertex3f(-20.0f, 0.0f, 20.0f);
193 
194         glTexCoord2f(0.0f, 0.0f);
195         glVertex3f(-20.0f, 0.0f, -20.0f);
196 
197         glTexCoord2f(1.0f, 0.0f);
198         glVertex3f(20.0f, 0.0f, -20.0f);
199 
200         glTexCoord2f(1.0f, 1.0f);
201         glVertex3f(20.0f, 0.0f, 20.0f);
202     glEnd();
203 }
204 
205 /*
206  *  For now all we will do is clear the screen to the color we previously decided on,
207  *  clear the depth buffer and reset the scene. We wont draw anything yet.
208  */
209 int DrawGLScene(GLvoid)                                  // Here‘s where we do all the drawing
210 {
211     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
212     // Clip plane equations
213     double eqr[] = { 0.0f, -1.0f, 0.0f, 0.0f };         // Plane equation to use for the reflected objects
214     
215     glLoadIdentity();
216     glTranslatef(xpos, -5.0f, -50 + zpos);
217     glRotatef(30, 1.0f, 0.0f, 0.0f);
218     glColorMask(0, 0, 0, 0);           // Set color mask
219 
220     glEnable(GL_STENCIL_TEST);         // Stencil buffer
221     glStencilFunc(GL_ALWAYS, 1, 1);    // Always passes, 1 bit plane, 1 as mask
222     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);  // Set the stencil buffer to 1 where we draw any polygon
223 
224     glDisable(GL_DEPTH_TEST);
225     DrawFloor();                       // Draw the floor (Draws to the stencil buffer)
226 
227     glEnable(GL_DEPTH_TEST);
228     glColorMask(1, 1, 1, 1);
229     glStencilFunc(GL_EQUAL, 1, 1);
230     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);     // Don‘t change the stencil buffer
231 
232     glEnable(GL_CLIP_PLANE0);                   // Enable clip plane for removing artifacts
233     glClipPlane(GL_CLIP_PLANE0, eqr);           // Equation for reflected objects
234     glPushMatrix();
235         glScalef(1.0f, -1.0f, 1.0f);                // Mirror Y axis
236 
237         glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
238         glTranslatef(-xpos, height, -zpos);
239         if (xpos > 20 || xpos < -20 || zpos > 20 || zpos < -20) {
240             heightspeed -= 0.0001f;
241             glTranslatef(-xpos, height, -zpos);
242         }
243         glRotatef((xrot + zrot) / 2, 0.5f, 0.0f, 0.5f);
244         DrawObject();
245     glPopMatrix();
246 
247     glDisable(GL_CLIP_PLANE0);
248     glDisable(GL_STENCIL_TEST);
249 
250     glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
251     glEnable(GL_BLEND);
252     glDisable(GL_LIGHTING);
253     glColor4f(1.0f, 1.0f, 1.0f, 0.8f);
254     // Blending based on source alpha and 1 minus dest alpha
255     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
256     DrawFloor();
257 
258     glEnable(GL_LIGHTING);
259     glDisable(GL_BLEND);
260     glTranslatef(-xpos, height, -zpos);
261     glRotatef((xrot + zrot) / 2, 0.5f, 0.0f, 0.5f);
262     DrawObject();
263 
264     xrot += xrotspeed;
265     zrot += zrotspeed;
266     xpos += xposspeed;
267     zpos += zposspeed;
268     height += heightspeed;
269     return true;
270 }
271 
272 void ProcessKeyboard()
273 {
274     if (keys[W] || keys[VK_UP]) {
275         zposspeed += 0.000005f;
276         xrotspeed -= 0.001f;
277     }
278 
279     if (keys[S] || keys[VK_DOWN]) {
280         zposspeed -= 0.000005f;
281         xrotspeed += 0.001f;
282     }
283 
284     if (keys[A] || keys[VK_LEFT]) {
285         xposspeed += 0.000005f;
286         zrotspeed += 0.001f;
287     }
288     if (keys[D] || keys[VK_RIGHT]) {
289         xposspeed -= 0.000005f;
290         zrotspeed -= 0.001f;
291     }
292 
293     if (keys[VK_PRIOR]) {
294         height += 0.003f;
295     }
296     if (keys[VK_NEXT]) {
297         height -= 0.003f;
298     }
299 }
300 
301 /******************************************************************************************************************************************/
302 /******************************************************************************************************************************************/
303 /*
304  *  The job of KillGLWindow() is to release the Rendering Context, 
305  *  the Device Context and finally the Window Handle. 
306  */
307 
308 GLvoid KillGLWindow(GLvoid)                              // Properly kill the window
309 {
310     if (fullscreen) {                                    // Are we in fullscreen mode
311         
312         /*
313          *  We use ChangeDisplaySettings(NULL,0) to return us to our original desktop.
314          *  After we‘ve switched back to the desktop we make the cursor visible again.
315          */
316 
317         ChangeDisplaySettings(NULL, 0);                  // if so switch back to the desktop
318         ShowCursor(TRUE);                                // Show mouse pointer
319     }
320 
321     if (hRC) {                                           // Do we have a rendering context
322         if (!wglMakeCurrent(NULL, NULL)) {                // Are we able to release the DC and RC contexts
323             MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
324         }
325 
326         if (!wglDeleteContext(hRC)) {                     // Are we able to delete the RC
327             MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
328             hRC = NULL;                                  // Set RC to NULL
329         }
330 
331         if (hDC && !ReleaseDC(hWnd, hDC)) {              // Are we able to release the DC
332             MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
333             hDC = NULL;                                  // Set DC to NULL
334         }
335         if (hWnd && !DestroyWindow(hWnd)) {              // Are we able to destroy the window
336             MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
337             hWnd = NULL;                                 // Set hWnd to NULL
338         }
339 
340         if (!UnregisterClass("OpenGL", hInstance)) {     // Are we able to unregister class
341             MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
342             hInstance = NULL;                            // Set hInstance to NULL
343         }
344     }
345 }
346 
347 /*
348  * The next section of code creates our OpenGL Window.
349  */
350 
351 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
352 {
353     /*
354      * Find  a pixel format that matches the one we want
355      */
356     GLuint PixelFormat;                                  // Holds the result after serching for a match
357     
358     /*
359      * Before you create a window, you MUST register a Class for the window
360      */
361     WNDCLASS wc;                                         // Windows class structure
362 
363     /*
364      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
365     */
366     DWORD dwExStyle;                                     // Window extend style
367     DWORD dwStyle;                                       // Window style
368 
369 
370     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
371     WindowRect.left = (long)0;                           // Set left value to 0
372     WindowRect.right = (long)width;                      // Set right value to requested width
373     WindowRect.top = (long)0;                            // Set top value to 0
374     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
375 
376     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
377 
378     /*
379      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 
380      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 
381      *  WndProc is the procedure that watches for messages in our program. 
382      *  No extra Window data is used so we zero the two fields. Then we set the instance. 
383      *  Next we set hIcon to NULL meaning we don‘t want an ICON in the Window, 
384      *  and for a mouse pointer we use the standard arrow. The background color doesn‘t matter 
385      *  (we set that in GL). We don‘t want a menu in this Window so we set it to NULL, 
386      *  and the class name can be any name you want. I‘ll use "OpenGL" for simplicity.
387      */
388     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
389     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
390     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
391     wc.cbClsExtra = 0;                                   // No extra window date
392     wc.cbWndExtra = 0;                                   // No extra window date
393     wc.hInstance = hInstance;                            // set the instance
394     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
395     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
396     wc.hbrBackground = NULL;                             // No background requried for GL
397     wc.lpszMenuName = NULL;                              // We don‘t want a menu
398     wc.lpszClassName = "OpenGL";                         // set the class name
399 
400     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
401         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
402         return FALSE;                                    // Exit and return false
403     }
404 
405     if (fullscreen) {                                    // attempt fullsreen model
406         
407         /*
408         T*  here are a few very important things you should keep in mind when switching to full screen mode.
409          *  Make sure the width and height that you use in fullscreen mode is the same as 
410          *  the width and height you plan to use for your window, and most importantly,
411          *  set fullscreen mode BEFORE you create your window.
412          */
413         DEVMODE dmScreenSettings;                        // Device mode
414         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory‘s cleared
415         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
416         dmScreenSettings.dmPelsWidth = width;            // Select window width
417         dmScreenSettings.dmPelsHeight = height;          // Select window height
418         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
419         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
420         
421         /*
422          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches 
423          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 
424          *  because it‘s supposed to remove the start bar at the bottom of the screen, 
425          *  plus it doesn‘t move or resize the windows on your desktop when you switch to 
426          *  fullscreen mode and back.
427          */
428         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
429         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
430             //If the mode fails, offer two options. Quit or run in a window
431             if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use"
432                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
433             {
434                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
435             }
436             else {
437                 // Pop up a message box letting user know the programe is closing.
438                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
439                 return FALSE;                             // Exit and return FALSE
440             }
441         }
442     }
443 
444     if (fullscreen) {                                     // Are we still in fullscreen mode
445         
446         /*
447          *  If we are still in fullscreen mode we‘ll set the extended style to WS_EX_APPWINDOW, 
448          *  which force a top level window down to the taskbar once our window is visible. 
449          *  For the window style we‘ll create a WS_POPUP window. 
450          *  This type of window has no border around it, making it perfect for fullscreen mode.
451 
452          *  Finally, we disable the mouse pointer. If your program is not interactive, 
453          *  it‘s usually nice to disable the mouse pointer when in fullscreen mode. It‘s up to you though.
454          */
455         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
456         dwStyle = WS_POPUP;                               // Window style
457         ShowCursor(FALSE);                                // Hide mosue pointer 
458     }
459     else {
460 
461         /*
462          *  If we‘re using a window instead of fullscreen mode, 
463          *  we‘ll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 
464          *  For style we‘ll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 
465          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 
466          *  window menu, and minimize / maximize buttons.
467          */
468         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
469         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
470     }
471 
472     /*
473      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 
474      *  instead, the window will be made larger to account for the pixels needed to draw the window border. 
475      *  In fullscreen mode, this command has no effect.
476      */
477     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
478     
479     /*
480      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 
481      *  These styles prevent other windows from drawing over or into our OpenGL Window.
482      */
483     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
484         "OpenGL",                                         // Class name
485         title,                                            // Window title
486         WS_CLIPSIBLINGS |                                 // Requried window style
487         WS_CLIPCHILDREN |                                 // Requried window style
488         dwStyle,                                          // Select window style
489         0, 0,                                             // Window position
490         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
491         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
492         NULL,                                             // No parent window
493         NULL,                                             // No menu
494         hInstance,                                        // Instance
495         NULL)))                                           // Don‘t pass anything to WM_CREATE
496     {
497         KillGLWindow();                                   //Reset the display
498         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
499         return FALSE;                                     // Retrurn FALSE;
500     }
501 
502     /*
503      *  aside from the stencil buffer and the (slow) accumulation buffer
504      */
505     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be 
506     {
507         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
508         1,                                                // Version number
509         PFD_DRAW_TO_WINDOW |                              // Format must support window
510         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
511         PFD_DOUBLEBUFFER,                                 // Must support double buffer
512         PFD_TYPE_RGBA,                                    // Request an RGBA format
513         bits,                                             // Select our color depth
514         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
515         0,                                                // No alpha buffer
516         0,                                                // shift bit ignored
517         0,                                                // No accumulation buffer
518         0, 0, 0, 0,                                       // Accumulation bits ignored
519         16,                                               // 16Bits Z_Buffer (depth buffer)
520 //******************************************************************************************************************************************/
521 //******************************************************************************************************************************************/
522         1,                                                // stencil buffer
523 //******************************************************************************************************************************************/
524 //******************************************************************************************************************************************/
525         0,                                                // No auxiliary buffer
526         PFD_MAIN_PLANE,                                   // Main drawing layer
527         0,                                                // Reserved
528         0, 0, 0                                           // Layer makes ignored
529     };
530 
531     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
532         KillGLWindow();                                   // Reset the display
533         MessageBox(NULL, "Can‘t create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
534         return FALSE;                                     // Return FALSE
535     }
536 
537     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
538         KillGLWindow();                                   // Reset the display
539         MessageBox(NULL, "Can‘t find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
540         return FALSE;                                     // Return FALSE;
541     }
542 
543     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
544         KillGLWindow();                                   // Reset the display
545         MessageBox(NULL, "Can‘t set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
546         return FALSE;                                     // Return FALSE;
547     }
548 
549     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
550         KillGLWindow();                                   // Reset the display
551         MessageBox(NULL, "Can‘t create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
552         return FALSE;                                     // Return FASLE;
553     }
554 
555     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
556         KillGLWindow();                                   // Reset the display
557         MessageBox(NULL, "Can‘t activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
558         return FALSE;                                     // Return FALSE    
559     }
560 
561     /*
562      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
563      */
564     ShowWindow(hWnd, SW_SHOW);                            // Show the window
565     SetForegroundWindow(hWnd);                            // slightly higher priority
566     SetFocus(hWnd);                                       // Sets keyboard focus to the window
567     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
568 
569 /*
570  *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
571  */
572     if (!InitGL()) {                                      // Initialize our newly created GL window
573         KillGLWindow();                                   // Reset the display
574         MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
575         return FALSE;                                     // Return FALSE
576     }
577     return TRUE;
578 }
579 
580 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
581     UINT uMsg,                                            // Message for this window
582     WPARAM wParam,                                        // Additional message information
583     LPARAM lParam)                                        // Additional message information
584 {
585     switch (uMsg) {                                       // Check for window message
586     case WM_ACTIVATE: {                               // Check minimization state
587         if (!HIWORD(wParam)) {
588             active = TRUE;                            // Program is active
589         }
590         else {
591             active = FALSE;                           // Program is no longer active
592         }
593         return 0;                                     // Return to the message loop
594     }
595     case WM_SYSCOMMAND: {                             // Intercept system commands
596         switch (wParam) {                             // Check system calls
597         case SC_SCREENSAVE:                       // Screensaver trying to start
598         case SC_MONITORPOWER:                     // Monitor trying to enter powersave
599             return 0;                                 // Prevent form happening
600         }
601         break;                                        // Exit
602     }
603     case WM_CLOSE: {                                  // Did we receive a close message
604         PostQuitMessage(0);                           // Send a quit message
605         return 0;
606     }
607     case WM_KEYDOWN: {                                // Is a key being held down
608         keys[wParam] = TRUE;                          // if so, mark it as TRUE
609         return 0;                                     // Jump back
610     }
611     case WM_KEYUP: {                                  // Has a key been released
612         keys[wParam] = FALSE;                         // if so, mark it as FALSE
613         return 0;                                     // Jump back
614     }
615     case WM_SIZE: {                                   // Resize the OpenGL window
616         ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));   // LoWord = width HiWord = height
617         return 0;                                     // Jump back
618     }
619     }
620     return DefWindowProc(hWnd, uMsg, wParam, lParam);     // Pass all unhandled message to DefWindwProc
621 }
622 
623 int WINAPI WinMain(HINSTANCE hInstance,                   // Instance
624     HINSTANCE hPrevInstance,                              // Previous instance
625     LPSTR lpCmdLine,                                      // Command line parameters
626     int nCmdShow)                                         // Window show state
627 {
628     MSG msg;                                              // Window message structure
629     BOOL done = FALSE;                                    // Bool variable to exit loop
630                                                           // Ask the user which screen mode they prefer
631     if (MessageBox(NULL, "Would you like to run in fullscreen mode?",
632         "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
633     {
634         fullscreen = FALSE;                               // Window mode
635     }
636     // Create our OpenGL window
637     if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {  // (Modified)
638         return 0;                                         // Quit if window was not create
639     }
640     while (!done) {                                       // Loop that runs until donw = TRUE
641         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {   // Is there a message wating
642             if (msg.message == WM_QUIT) {                 // Havw we received a quit message
643                 done = TRUE;                              // if so done  = TRUE
644             }
645             else {                                        // If not, deal with window message
646                 TranslateMessage(&msg);                   // Translate message
647                 DispatchMessage(&msg);                    // Dispatch message
648             }
649         }
650         else {
651             // Draw the scene. Watch for ESC key and quit message from DrawGLScene()
652             if (active) {                                 // Program active
653                 if (keys[VK_ESCAPE]) {                    // Was ESC pressed
654                     done = TRUE;                          // ESC signalled a quit
655                 }
656                 else {                                    // Not time to quit, update screen
657                     DrawGLScene();                        // Draw scene
658                     SwapBuffers(hDC);                     // Swap buffers (double buffering)
659 //******************************************************************************************************************************************/
660 //******************************************************************************************************************************************/
661                     ProcessKeyboard();
662 //******************************************************************************************************************************************/
663 //******************************************************************************************************************************************/
664 
665                 }
666             }
667             /*
668             *  It allows us to press the F1 key to switch from fullscreen mode to
669             *  windowed mode or windowed mode to fullscreen mode.
670             */
671             if (keys[VK_F1]) {                            // Is F1 being pressed
672                 keys[VK_F1] = FALSE;                      // If so make key FASLE
673                 KillGLWindow();                           // Kill our current window
674                 fullscreen = !fullscreen;                 // Toggle fullscreen / window mode
675                 //Recreate our OpenGL window(modified)
676                 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {
677                     return 0;                             // Quit if window was not create
678                 }
679             }
680         }
681     }
682     // Shutdown
683     KillGLWindow();                                       // Kill the window
684     return (msg.wParam);                                  // Exit the program
685 }
686 /******************************************************************************************************************************************/
687 /******************************************************************************************************************************************/

 

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

outdated: 26.Clipping & Reflections Using The Stencil Buffer

标签:

原文地址:http://www.cnblogs.com/clairvoyant/p/5726756.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!