outdated: 24.Tokens, Extensions, Scissor Testing And TGA Loading

这一篇主要说的是,怎样实现在窗口中裁剪一个小的视图窗口(即glScissor()函数)?以及对glGetString()函数的应用。

在本文中,用到的贴图材质是TGA格式图片,相对于JPG格式,会更加清晰,因使用不失真的压缩。不了解TGA格式图片的可以看看这篇。基于对TGA格式的了解,具有独有的一个8位的Alpha通道。在其代码中,在24位和32位之间来转换,差的8位即为Alpha。所以,一开始会有一个变量type,默认为32位---GL_RGBA。支持扩展是很好的一个特性,使得DrawGLScene()函数中的glGetString()函数可以使用。

LoadTGA()函数中,只会加载24位和32位的TGA,首先第一个变量,

GLubyte TGAheader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

在与所读文件前12个字节比较后,确保是Targa文件。

下一个变量,

GLubyte header[6];

读取宽(位置)、高(位置)和每像素值的比特位,共6字节。

glPrint函数中的glScalef()函数用来设置字体的形变。

DrawGLScene()函数中的glGetString()函数,其参数有四个,依次为渲染器,渲染器出处,渲染器版本,支持的扩展。

 Meaning
GL_VENDOR

Returns the company responsible for this OpenGL implementation. This name does not change from release to release.

GL_RENDERER

Returns the name of the renderer. This name is typically specific to a particular configuration of a hardware platform. It does not change from release to release.

GL_VERSION

Returns a version or release number.

GL_EXTENSIONS

Returns a space-separated list of supported extensions to OpenGL.

glScissor()函数,设置一个小窗口,当然都是在windows窗体的限制内。

void WINAPI glScissor(
   GLint   x,
   GLint   y,
   GLsizei width,
   GLsizei height
);

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

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

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

posted @ 2016-07-30 12:08  clairvoyant  阅读(345)  评论(0编辑  收藏  举报