outdated: 19.Particle Engine Using Triangle Strips

粒子散射做出来是比较酷炫的,每个粒子为一个结构体。

1 typedef struct {
2     bool active;                                      // Active
3     float life;                                       // Particle life
4     float fade;                                       // Fade speed
5     float r, g, b;
6     float x, y, z;                                    // Position
7     float xi, yi, zi;                                 // Direction
8     float xg, yg, zg;                                 // Gravity
9 } particles;

活动状态、生命周期、消褪时间、颜色、位置坐标、方向坐标、重力方向都有,可以任意调节。

当时在绘制函数中发现原文用的是三角形,为什么不用四边形?

1 glBegin(GL_TRIANGLE_STRIP)

因为用Quads很慢,现在的GPU都呈现三角形,尽力呈现(其实为相似)四边形。原因此处

在InitGL()函数内,对1000个结构体进行初始化,除了位置坐标和颜色。

在DrawGLScene()函数内,再对位置坐标和颜色修改后进行绘制。

我修改了部分按键,最终为W/S/A/D为重力方向,UP/DOWN/LEFT/RIGHT为总体方向,小键盘的-/+为粒子速度的调节,PgUp/PgDn为粒子于屏幕的远近,tab键让所有粒子都回到原点,空格键切换颜色,enter键位单色和多色之间的转换。

原图:

当绘制的为点时:

当绘制的为线时:

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

  1 #include <windows.h>
  2 #include <stdio.h>
  3 #include <math.h>
  4 #include <gl/glew.h>
  5 #include <gl/glut.h>
  6 #include <GL/GLUAX.H>
  7 #pragma comment(lib, "legacy_stdio_definitions.lib")
  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 /******************************************************************************************************************************************/
 31 #define MAX_PARTICLES 1000
 32 bool rainbow = true;
 33 bool rp;
 34 bool sp;                // Spacebar pressed
 35 
 36 float slowdown = 2.0f;  // Slow down particles
 37 float xspeed;
 38 float yspeed;
 39 float zoom = -40.0f;    // Used to zoom out
 40 
 41 GLuint loop;
 42 GLuint col;
 43 GLuint delay;
 44 GLuint texture[1];
 45 
 46 typedef struct {
 47     bool active;                                      // Active
 48     float life;                                       // Particle life
 49     float fade;                                       // Fade speed
 50     float r, g, b;
 51     float x, y, z;                                    // Position
 52     float xi, yi, zi;                                 // Direction
 53     float xg, yg, zg;                                 // Gravity
 54 } particles;
 55 
 56 particles particle[MAX_PARTICLES];
 57 
 58 static GLfloat colors[12][3] = {
 59     { 1.0f,0.5f,0.5f },{ 1.0f,0.75f,0.5f },{ 1.0f,1.0f,0.5f },{ 0.75f,1.0f,0.5f },
 60     { 0.5f,1.0f,0.5f },{ 0.5f,1.0f,0.75f },{ 0.5f,1.0f,1.0f },{ 0.5f,0.75f,1.0f },
 61     { 0.5f,0.5f,1.0f },{ 0.75f,0.5f,1.0f },{ 1.0f,0.5f,1.0f },{ 1.0f,0.5f,0.75f }
 62 };
 63 
 64 /******************************************************************************************************************************************/
 65 /******************************************************************************************************************************************/
 66 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
 67 
 68 AUX_RGBImageRec* LoadBMP(char* Filename)
 69 {
 70     FILE* File = NULL;
 71     
 72     if (!Filename) {
 73         return NULL;
 74     }
 75 
 76     File = fopen(Filename, "r");
 77     if (File) {
 78         fclose(File);
 79         return auxDIBImageLoad(Filename);
 80     }
 81 
 82     return NULL;
 83 }
 84 
 85 int LoadGLTextures()
 86 {
 87     int Status = FALSE;
 88 
 89 /******************************************************************************************************************************************/
 90 /******************************************************************************************************************************************/
 91     AUX_RGBImageRec* TextureImage[1];
 92     
 93     memset(TextureImage, 0, sizeof(void*) * 1);
 94 
 95     if (TextureImage[0] = LoadBMP("1.bmp")) {
 96         Status = TRUE;
 97         glGenTextures(3, &texture[0]);
 98 
 99         glBindTexture(GL_TEXTURE_2D, texture[0]);
100         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
101         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
102         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY,
103             0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
104     }
105 
106     if (TextureImage[0]) {
107         if (TextureImage[0]->data) {
108             free(TextureImage[0]->data);
109         }
110         free(TextureImage[0]);
111     }
112     return Status;
113 }
114 /******************************************************************************************************************************************/
115 /******************************************************************************************************************************************/
116 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
117 {
118     if (height == 0) {                                // Prevent a divide by zero by
119         height = 1;                                   // Making height equal one
120     }
121     
122     glViewport(0, 0, width, height);                  // Reset the current viewport
123 
124     /*
125      *  The following lines set the screen up for a perspective view. 
126      *  Meaning things in the distance get smaller. This creates a realistic looking scene. 
127      *  The perspective is calculated with a 45 degree viewing angle based on 
128      *  the windows width and height. The 0.1f, 100.0f is the starting point and 
129      *  ending point for how deep we can draw into the screen.
130      *
131      *  The projection matrix is responsible for adding perspective to our scene.
132      *  glLoadIdentity() restores the selected matrix to it's original state.
133      *  The modelview matrix is where our object information is stored.
134      *   Lastly we reset the modelview matrix.
135      */
136 
137     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
138     glLoadIdentity();                                 // Reset the projection matrix
139     
140                                                       // Calculate the aspect ratio of the window
141     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
142 
143     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
144     glLoadIdentity();                                 // Reset the modelview matrix
145 }
146 /******************************************************************************************************************************************/
147 /******************************************************************************************************************************************/
148 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
149 {
150     /*
151      *  Smooth shading blends colors nicely across a polygon, and smoothes out lighting.
152      */
153 
154     if (!LoadGLTextures()) {
155         return FALSE;
156     }
157 
158     glEnable(GL_TEXTURE_2D);
159     glShadeModel(GL_SMOOTH);                          // Enables smooth shading
160     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);             // Black background
161 
162     glClearDepth(1.0f);                               // Depth buffer setup
163 
164     glDisable(GL_DEPTH_TEST);
165     glEnable(GL_BLEND);
166     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
167 
168     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
169 
170     glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);           // Really nice perspective calculations
171     glBindTexture(GL_TEXTURE_2D, texture[0]);
172 
173     for (loop = 0; loop < MAX_PARTICLES; ++loop) {     // Initialize all the textures
174         particle[loop].active = true;                  // Make all the particles active
175         particle[loop].life = 1.0f;                    // Give all the particles full life
176         particle[loop].fade = float(rand() % 100) / 1000.0f + 0.003f;    // Random fade speed
177         
178         particle[loop].r = colors[loop * (12 / MAX_PARTICLES)][0];
179         particle[loop].g = colors[loop * (12 / MAX_PARTICLES)][1];
180         particle[loop].b = colors[loop * (12 / MAX_PARTICLES)][2];
181 
182         particle[loop].xi = float((rand() % 50) - 26.0f) * 10.0f;        // Direction
183         particle[loop].yi = float((rand() % 50) - 25.0f) * 10.0f;
184         particle[loop].zi = float((rand() % 50) - 25.0f) * 10.0f;
185 
186         particle[loop].xg = 0.0f;                                        // Gravity
187         particle[loop].yg = -0.8f;
188         particle[loop].zg = 0.0f;
189     }
190 
191     return TRUE;
192 }
193 
194 /*
195  *  For now all we will do is clear the screen to the color we previously decided on,
196  *  clear the depth buffer and reset the scene. We wont draw anything yet.
197  */
198 int DrawGLScene(GLvoid)                                  // Here's where we do all the drawing
199 {
200     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear the screen and the depth buffer
201     glLoadIdentity();
202 
203     for (loop = 0; loop < MAX_PARTICLES; ++loop) {
204         if (particle[loop].active) {
205             float x = particle[loop].x;
206             float y = particle[loop].y;
207             float z = particle[loop].z+zoom;
208 
209             glColor4f(particle[loop].r, particle[loop].g, particle[loop].b, particle[loop].life);
210 
211             glBegin(GL_TRIANGLE_STRIP);
212                 glTexCoord2d(1, 1); glVertex3f(x + 0.5f, y + 0.5f, z);  // Top right
213                 glTexCoord2d(0, 1); glVertex3f(x - 0.5f, y + 0.5f, z);  // Top left
214                 glTexCoord2d(1, 0); glVertex3f(x + 0.5f, y - 0.5f, z);  // Bottom right
215                 glTexCoord2d(0, 0); glVertex3f(x - 0.5f, y - 0.5f, z);  // Bottom left
216             glEnd();
217             // Move on the X axis by X speed
218             particle[loop].x += particle[loop].xi / (slowdown * MAX_PARTICLES);
219             // Move on the Y axis by Y speed
220             particle[loop].y += particle[loop].yi / (slowdown * MAX_PARTICLES);
221             // Move On The Z Axis By Z Speed
222             particle[loop].z += particle[loop].zi / (slowdown * MAX_PARTICLES);
223 
224             particle[loop].xi += particle[loop].xg;  // Take pull on X axis into account
225             particle[loop].yi += particle[loop].yg;  // Take pull on Y aixs into account
226             particle[loop].zi += particle[loop].zg;  // Take pull on Z axis into account
227 
228             particle[loop].life -= particle[loop].fade;  // Reduce particles life by 'fade'
229 
230             if (particle[loop].life < 0.0f) {
231                 particle[loop].life = 1.0;
232                 particle[loop].fade = float(rand() % 100) / MAX_PARTICLES + 0.003f;
233 
234                 particle[loop].x = 0.0f;                 // Center
235                 particle[loop].y = 0.0f;
236                 particle[loop].z = 0.0f;
237 
238                 particle[loop].xi = xspeed + float((rand() % 60) - 32.0f);
239                 particle[loop].yi = yspeed + float((rand() % 60) - 32.0f);
240                 particle[loop].zi = float((rand() % 60) - 32.0f);
241 
242                 particle[loop].r = colors[col][0];
243                 particle[loop].g = colors[col][1];
244                 particle[loop].b = colors[col][2];
245             }
246 
247             if (keys['W'] && (particle[loop].yg < 1.5f)) {
248                 particle[loop].yg += 0.01f;
249             }
250             if (keys['S'] && (particle[loop].yg > -1.5f)) {
251                 particle[loop].yg -= 0.01f;
252             }
253             if (keys['D'] && (particle[loop].xg < 1.5f)) {
254                 particle[loop].xg += 0.01f;
255             }
256             if (keys['A'] && (particle[loop].xg > -1.5f)) {
257                 particle[loop].xg -= 0.01f;
258             }
259 
260             if (keys[VK_TAB]) {
261                 particle[loop].x = 0.0f;
262                 particle[loop].y = 0.0f;
263                 particle[loop].z = 0.0f;
264                 particle[loop].xi = float((rand() % 50) - 26.0f) * 10.0f;
265                 particle[loop].yi = float((rand() % 50) - 26.0f) * 10.0f;
266                 particle[loop].zi = float((rand() % 50) - 26.0f) * 10.0f;
267             }
268         }
269     }
270 
271     return TRUE;                                         // everthing went OK
272 }
273 /******************************************************************************************************************************************/
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 /******************************************************************************************************************************************/
321 }
322 
323 /*
324  * The next section of code creates our OpenGL Window.
325  */
326 
327 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
328 {
329     /*
330      * Find  a pixel format that matches the one we want
331      */
332     GLuint PixelFormat;                                  // Holds the result after serching for a match
333     
334     /*
335      * Before you create a window, you MUST register a Class for the window
336      */
337     WNDCLASS wc;                                         // Windows class structure
338 
339     /*
340      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
341     */
342     DWORD dwExStyle;                                     // Window extend style
343     DWORD dwStyle;                                       // Window style
344 
345     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
346     WindowRect.left = (long)0;                           // Set left value to 0
347     WindowRect.right = (long)width;                      // Set right value to requested width
348     WindowRect.top = (long)0;                            // Set top value to 0
349     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
350 
351     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
352 
353     /*
354      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 
355      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 
356      *  WndProc is the procedure that watches for messages in our program. 
357      *  No extra Window data is used so we zero the two fields. Then we set the instance. 
358      *  Next we set hIcon to NULL meaning we don't want an ICON in the Window, 
359      *  and for a mouse pointer we use the standard arrow. The background color doesn't matter 
360      *  (we set that in GL). We don't want a menu in this Window so we set it to NULL, 
361      *  and the class name can be any name you want. I'll use "OpenGL" for simplicity.
362      */
363     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
364     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
365     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
366     wc.cbClsExtra = 0;                                   // No extra window date
367     wc.cbWndExtra = 0;                                   // No extra window date
368     wc.hInstance = hInstance;                            // set the instance
369     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
370     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
371     wc.hbrBackground = NULL;                             // No background requried for GL
372     wc.lpszMenuName = NULL;                              // We don't want a menu
373     wc.lpszClassName = "OpenGL";                         // set the class name
374 
375     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
376         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
377         return FALSE;                                    // Exit and return false
378     }
379 
380     if (fullscreen) {                                    // attempt fullsreen model
381         
382         /*
383         T*  here are a few very important things you should keep in mind when switching to full screen mode.
384          *  Make sure the width and height that you use in fullscreen mode is the same as 
385          *  the width and height you plan to use for your window, and most importantly,
386          *  set fullscreen mode BEFORE you create your window.
387          */
388         DEVMODE dmScreenSettings;                        // Device mode
389         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared
390         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
391         dmScreenSettings.dmPelsWidth = width;            // Select window width
392         dmScreenSettings.dmPelsHeight = height;          // Select window height
393         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
394         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
395         
396         /*
397          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches 
398          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 
399          *  because it's supposed to remove the start bar at the bottom of the screen, 
400          *  plus it doesn't move or resize the windows on your desktop when you switch to 
401          *  fullscreen mode and back.
402          */
403         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
404         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
405             //If the mode fails, offer two options. Quit or run in a window
406             if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use"
407                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
408             {
409                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
410             }
411             else {
412                 // Pop up a message box letting user know the programe is closing.
413                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
414                 return FALSE;                             // Exit and return FALSE
415             }
416         }
417     }
418 
419     if (fullscreen) {                                     // Are we still in fullscreen mode
420         
421         /*
422          *  If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 
423          *  which force a top level window down to the taskbar once our window is visible. 
424          *  For the window style we'll create a WS_POPUP window. 
425          *  This type of window has no border around it, making it perfect for fullscreen mode.
426 
427          *  Finally, we disable the mouse pointer. If your program is not interactive, 
428          *  it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though.
429          */
430         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
431         dwStyle = WS_POPUP;                               // Window style
432         ShowCursor(FALSE);                                // Hide mosue pointer 
433     }
434     else {
435 
436         /*
437          *  If we're using a window instead of fullscreen mode, 
438          *  we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 
439          *  For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 
440          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 
441          *  window menu, and minimize / maximize buttons.
442          */
443         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
444         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
445     }
446 
447     /*
448      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 
449      *  instead, the window will be made larger to account for the pixels needed to draw the window border. 
450      *  In fullscreen mode, this command has no effect.
451      */
452     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
453     
454     /*
455      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 
456      *  These styles prevent other windows from drawing over or into our OpenGL Window.
457      */
458     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
459         "OpenGL",                                         // Class name
460         title,                                            // Window title
461         WS_CLIPSIBLINGS |                                 // Requried window style
462         WS_CLIPCHILDREN |                                 // Requried window style
463         dwStyle,                                          // Select window style
464         0, 0,                                             // Window position
465         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
466         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
467         NULL,                                             // No parent window
468         NULL,                                             // No menu
469         hInstance,                                        // Instance
470         NULL)))                                           // Don't pass anything to WM_CREATE
471     {
472         KillGLWindow();                                   //Reset the display
473         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
474         return FALSE;                                     // Retrurn FALSE;
475     }
476 
477     /*
478      *  aside from the stencil buffer and the (slow) accumulation buffer
479      */
480     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be 
481     {
482         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
483         1,                                                // Version number
484         PFD_DRAW_TO_WINDOW |                              // Format must support window
485         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
486         PFD_DOUBLEBUFFER,                                 // Must support double buffer
487         PFD_TYPE_RGBA,                                    // Request an RGBA format
488         bits,                                             // Select our color depth
489         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
490         0,                                                // No alpha buffer
491         0,                                                // shift bit ignored
492         0,                                                // No accumulation buffer
493         0, 0, 0, 0,                                       // Accumulation bits ignored
494         16,                                               // 16Bits Z_Buffer (depth buffer)
495         0,                                                // No stencil buffer
496         0,                                                // No auxiliary buffer
497         PFD_MAIN_PLANE,                                   // Main drawing layer
498         0,                                                // Reserved
499         0, 0, 0                                           // Layer makes ignored
500     };
501 
502     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
503         KillGLWindow();                                   // Reset the display
504         MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
505         return FALSE;                                     // Return FALSE
506     }
507 
508     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
509         KillGLWindow();                                   // Reset the display
510         MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
511         return FALSE;                                     // Return FALSE;
512     }
513 
514     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
515         KillGLWindow();                                   // Reset the display
516         MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
517         return FALSE;                                     // Return FALSE;
518     }
519 
520     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
521         KillGLWindow();                                   // Reset the display
522         MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
523         return FALSE;                                     // Return FASLE;
524     }
525 
526     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
527         KillGLWindow();                                   // Reset the display
528         MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
529         return FALSE;                                     // Return FALSE    
530     }
531 
532     /*
533      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
534      */
535     ShowWindow(hWnd, SW_SHOW);                            // Show the window
536     SetForegroundWindow(hWnd);                            // slightly higher priority
537     SetFocus(hWnd);                                       // Sets keyboard focus to the window
538     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
539 
540 /*
541  *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
542  */
543 if (!InitGL()) {                                      // Initialize our newly created GL window
544     KillGLWindow();                                   // Reset the display
545     MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
546     return FALSE;                                     // Return FALSE
547 }
548 return TRUE;
549 }
550 
551 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
552     UINT uMsg,                                            // Message for this window
553     WPARAM wParam,                                        // Additional message information
554     LPARAM lParam)                                        // Additional message information
555 {
556     switch (uMsg) {                                       // Check for window message
557     case WM_ACTIVATE: {                               // Check minimization state
558         if (!HIWORD(wParam)) {
559             active = TRUE;                            // Program is active
560         }
561         else {
562             active = FALSE;                           // Program is no longer active
563         }
564         return 0;                                     // Return to the message loop
565     }
566     case WM_SYSCOMMAND: {                             // Intercept system commands
567         switch (wParam) {                             // Check system calls
568         case SC_SCREENSAVE:                       // Screensaver trying to start
569         case SC_MONITORPOWER:                     // Monitor trying to enter powersave
570             return 0;                                 // Prevent form happening
571         }
572         break;                                        // Exit
573     }
574     case WM_CLOSE: {                                  // Did we receive a close message
575         PostQuitMessage(0);                           // Send a quit message
576         return 0;
577     }
578     case WM_KEYDOWN: {                                // Is a key being held down
579         keys[wParam] = TRUE;                          // if so, mark it as TRUE
580         return 0;                                     // Jump back
581     }
582     case WM_KEYUP: {                                  // Has a key been released
583         keys[wParam] = FALSE;                         // if so, mark it as FALSE
584         return 0;                                     // Jump back
585     }
586     case WM_SIZE: {                                   // Resize the OpenGL window
587         ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));   // LoWord = width HiWord = height
588         return 0;                                     // Jump back
589     }
590     }
591     return DefWindowProc(hWnd, uMsg, wParam, lParam);     // Pass all unhandled message to DefWindwProc
592 }
593 
594 int WINAPI WinMain(HINSTANCE hInstance,                   // Instance
595     HINSTANCE hPrevInstance,                              // Previous instance
596     LPSTR lpCmdLine,                                      // Command line parameters
597     int nCmdShow)                                         // Window show state
598 {
599     MSG msg;                                              // Window message structure
600     BOOL done = FALSE;                                    // Bool variable to exit loop
601                                                           // Ask the user which screen mode they prefer
602     if (MessageBox(NULL, "Would you like to run in fullscreen mode?",
603         "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
604     {
605         fullscreen = FALSE;                               // Window mode
606     }
607     // Create our OpenGL window
608     if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {  // (Modified)
609         return 0;                                         // Quit if window was not create
610     }
611 
612     while (!done) {                                       // Loop that runs until donw = TRUE
613         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {   // Is there a message wating
614             if (msg.message == WM_QUIT) {                 // Havw we received a quit message
615                 done = TRUE;                              // if so done  = TRUE
616             }
617             else {                                        // If not, deal with window message
618                 TranslateMessage(&msg);                   // Translate message
619                 DispatchMessage(&msg);                    // Dispatch message
620             }
621         }
622         else {
623             // Draw the scene. Watch for ESC key and quit message from DrawGLScene()
624             if (active) {                                 // Program active
625                 if (keys[VK_ESCAPE]) {                    // Was ESC pressed
626                     done = TRUE;                          // ESC signalled a quit
627                 }
628                 else {                                    // Not time to quit, update screen
629                     DrawGLScene();                        // Draw scene
630                     SwapBuffers(hDC);                     // Swap buffers (double buffering)
631                 }
632             }
633 /******************************************************************************************************************************************/
634 /******************************************************************************************************************************************/
635             if (keys[VK_ADD] && (slowdown > 1.0f)) {
636                 slowdown -= 0.01f;
637             }
638             if (keys[VK_SUBTRACT] && (slowdown < 4.0f)) {
639                 slowdown += 0.01f;
640             }
641             if (keys[VK_PRIOR]) {
642                 zoom += 0.01f;
643             }
644             if (keys[VK_NEXT]) {
645                 zoom -= 0.01f;
646             }
647 
648             if (keys[VK_RETURN]&& !rp) {
649                 rp = true;
650                 rainbow = !rainbow;
651             }
652             if (!keys[VK_RETURN]) {
653                 rp = false;
654             }
655 
656             if ((keys[' '] && !sp) || (rainbow && (delay > 25))) {
657                 if (keys[' ']) {
658                     rainbow = false;
659                 }
660                 sp = true;
661                 delay = 0;
662                 col++;
663                 if (col > 11) {
664                     col = 0;
665                 }
666             }
667             if (!keys[' ']) {
668                 sp = false;
669             }
670 
671             if (keys[VK_UP] && (yspeed < 200)) {
672                 yspeed += 1.0f;
673             }
674             if (keys[VK_DOWN] && (yspeed > -200)) {
675                 yspeed -= 1.0f;
676             }
677             if (keys[VK_RIGHT] && (xspeed < 200)) {
678                 xspeed += 1.0f;
679             }
680             if (keys[VK_LEFT] && (xspeed > -200)) {
681                 xspeed -= 1.0f;
682             }
683             delay++;
684 /******************************************************************************************************************************************/
685 /******************************************************************************************************************************************/
686             /*
687             *  It allows us to press the F1 key to switch from fullscreen mode to
688             *  windowed mode or windowed mode to fullscreen mode.
689             */
690             if (keys[VK_F1]) {                            // Is F1 being pressed
691                 keys[VK_F1] = FALSE;                      // If so make key FASLE
692                 KillGLWindow();                           // Kill our current window
693                 fullscreen = !fullscreen;                 // Toggle fullscreen / window mode
694                 //Recreate our OpenGL window(modified)
695                 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {
696                     return 0;                             // Quit if window was not create
697                 }
698             }
699         }
700     }
701     // Shutdown
702     KillGLWindow();                                       // Kill the window
703     return (msg.wParam);                                  // Exit the program
704 }

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

posted @ 2016-07-16 21:28  clairvoyant  阅读(258)  评论(0编辑  收藏  举报