标签:
这一章实现了物体在地面上的投影,以及物体表面灯光闪烁的效果。
我在原本的代码上添加了些功能,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