OpenGL窗口

Posted clairvoyant

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL窗口相关的知识,希望对你有一定的参考价值。

  1 #include <windows.h>
  2 #include <gl/glew.h>
  3 #include <gl/glut.h>
  4 
  5 /*
  6  *  Every OpenGL program is linked to a Rendering Context.
  7  *  A Rendering Context is what links OpenGL calls to the Device Context.
  8  *  In order for your program to draw to a Window you need to create a Device Context.
  9  *  The DC connects the Window to the GDI (Graphics Device Interface).
 10  */
 11 
 12 HGLRC     hRC = NULL;         // Permanent rendering context
 13 HDC       hDC = NULL;         // Private GDI device context
 14 HWND      hWnd = NULL;        // Holds our window handle
 15 HINSTANCE hInstance;          // Holds the instance of the application
 16 
 17 /*
 18  *  It‘s important to make this global so that each procedure knows if 
 19  *  the program is running in fullscreen mode or not.
 20  */
 21 
 22 bool keys[256];         // Array used for the keyboard routine
 23 bool active = TRUE;     // Window active flag set to TRUE by default
 24 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default
 25 
 26 /*
 27  *  CreateGLWindow() has a reference to WndProc() but WndProc() comes after CreateGLWindow().
 28  */
 29 
 30 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
 31 
 32 /*
 33  *  The job of the next section of code is to resize the OpenGL scene 
 34  *  whenever the window (assuming you are using a Window rather than fullscreen mode) has been resized.
 35  */
 36 
 37 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
 38 {
 39     if (height == 0) {                                // Prevent a divide by zero by
 40         height = 1;                                   // Making height equal one
 41     }
 42     
 43     glViewport(0, 0, width, height);                  // Reset the current viewport
 44 
 45     /*
 46      *  The following lines set the screen up for a perspective view. 
 47      *  Meaning things in the distance get smaller. This creates a realistic looking scene. 
 48      *  The perspective is calculated with a 45 degree viewing angle based on 
 49      *  the windows width and height. The 0.1f, 100.0f is the starting point and 
 50      *  ending point for how deep we can draw into the screen.
 51      *
 52      *  The projection matrix is responsible for adding perspective to our scene.
 53      *  glLoadIdentity() restores the selected matrix to it‘s original state.
 54      *  The modelview matrix is where our object information is stored.
 55      *   Lastly we reset the modelview matrix.
 56      */
 57 
 58     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
 59     glLoadIdentity();                                 // Reset the projection matrix
 60     
 61                                                       // Calculate the aspect ratio of the window
 62     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
 63 
 64     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
 65     glLoadIdentity();                                 // Reset the modelview matrix
 66 }
 67 
 68 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
 69 {
 70     /*
 71      *  Smooth shading blends colors nicely across a polygon, and smoothes out lighting.
 72      */
 73     
 74     glShadeModel(GL_SMOOTH);                          // Enables smooth shading
 75 
 76     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);             // Black background
 77 
 78     /*
 79      *  Think of the depth buffer as layers into the screen. 
 80      *  The depth buffer keeps track of how deep objects are into the screen.
 81      */
 82 
 83     glClearDepth(1.0f);                               // Depth buffer setup
 84     glEnable(GL_DEPTH_TEST);                          // Enable depth testing
 85     glDepthFunc(GL_LEQUAL);                           // The typr of depth test to do
 86 
 87     /*
 88      *  Next we tell OpenGL we want the best perspective correction to be done. 
 89      *  This causes a very tiny performance hit, but makes the perspective view look a bit better.
 90      */
 91 
 92     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // Really nice perspective calculations
 93 
 94     return TRUE;
 95 }
 96 
 97 /*
 98  *  For now all we will do is clear the screen to the color we previously decided on, 
 99  *  clear the depth buffer and reset the scene. We wont draw anything yet.
100  */
101 
102 int DrawGLScene(GLvoid)                                  // Here‘s where we do all the drawing
103 {
104     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear the screen and the depth buffer
105     glLoadIdentity();                                    // Reset the current modelview matrix
106     return TRUE;                                         // everthing went OK
107 }
108 
109 /*
110  *  The job of KillGLWindow() is to release the Rendering Context, 
111  *  the Device Context and finally the Window Handle. 
112  */
113 
114 GLvoid KillGLWindow(GLvoid)                              // Properly kill the window
115 {
116     if (fullscreen) {                                    // Are we in fullscreen mode
117         
118         /*
119          *  We use ChangeDisplaySettings(NULL,0) to return us to our original desktop.
120          *  After we‘ve switched back to the desktop we make the cursor visible again.
121          */
122 
123         ChangeDisplaySettings(NULL, 0);                  // if so switch back to the desktop
124         ShowCursor(TRUE);                                // Show mouse pointer
125     }
126 
127     if (hRC) {                                           // Do we have a rendering context
128         if (!wglMakeCurrent(NULL, NULL)) {                // Are we able to release the DC and RC contexts
129             MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
130         }
131 
132         if (!wglDeleteContext(hRC)) {                     // Are we able to delete the RC
133             MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
134             hRC = NULL;                                  // Set RC to NULL
135         }
136 
137         if (hDC && !ReleaseDC(hWnd, hDC)) {              // Are we able to release the DC
138             MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
139             hDC = NULL;                                  // Set DC to NULL
140         }
141         if (hWnd && !DestroyWindow(hWnd)) {              // Are we able to destroy the window
142             MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
143             hWnd = NULL;                                 // Set hWnd to NULL
144         }
145 
146         if (!UnregisterClass("OpenGL", hInstance)) {     // Are we able to unregister class
147             MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
148             hInstance = NULL;                            // Set hInstance to NULL
149         }
150     }
151 }
152 
153 /*
154  * The next section of code creates our OpenGL Window.
155  */
156 
157 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
158 {
159     /*
160      * Find  a pixel format that matches the one we want
161      */
162     GLuint PixelFormat;                                  // Holds the result after serching for a match
163     
164     /*
165      * Before you create a window, you MUST register a Class for the window
166      */
167     WNDCLASS wc;                                         // Windows class structure
168 
169     /*
170      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
171     */
172     DWORD dwExStyle;                                     // Window extend style
173     DWORD dwStyle;                                       // Window style
174 
175     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
176     WindowRect.left = (long)0;                           // Set left value to 0
177     WindowRect.right = (long)width;                      // Set right value to requested width
178     WindowRect.top = (long)0;                            // Set top value to 0
179     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
180 
181     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
182 
183     /*
184      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 
185      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 
186      *  WndProc is the procedure that watches for messages in our program. 
187      *  No extra Window data is used so we zero the two fields. Then we set the instance. 
188      *  Next we set hIcon to NULL meaning we don‘t want an ICON in the Window, 
189      *  and for a mouse pointer we use the standard arrow. The background color doesn‘t matter 
190      *  (we set that in GL). We don‘t want a menu in this Window so we set it to NULL, 
191      *  and the class name can be any name you want. I‘ll use "OpenGL" for simplicity.
192      */
193     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
194     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
195     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
196     wc.cbClsExtra = 0;                                   // No extra window date
197     wc.cbWndExtra = 0;                                   // No extra window date
198     wc.hInstance = hInstance;                            // set the instance
199     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
200     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
201     wc.hbrBackground = NULL;                             // No background requried for GL
202     wc.lpszMenuName = NULL;                              // We don‘t want a menu
203     wc.lpszClassName = "OpenGL";                         // set the class name
204 
205     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
206         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
207         return FALSE;                                    // Exit and return false
208     }
209 
210     if (fullscreen) {                                    // attempt fullsreen model
211         
212         /*
213         T*  here are a few very important things you should keep in mind when switching to full screen mode.
214          *  Make sure the width and height that you use in fullscreen mode is the same as 
215          *  the width and height you plan to use for your window, and most importantly,
216          *  set fullscreen mode BEFORE you create your window.
217          */
218         DEVMODE dmScreenSettings;                        // Device mode
219         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory‘s cleared
220         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
221         dmScreenSettings.dmPelsWidth = width;            // Select window width
222         dmScreenSettings.dmPelsHeight = height;          // Select window height
223         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
224         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
225         
226         /*
227          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches 
228          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 
229          *  because it‘s supposed to remove the start bar at the bottom of the screen, 
230          *  plus it doesn‘t move or resize the windows on your desktop when you switch to 
231          *  fullscreen mode and back.
232          */
233         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
234         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
235             //If the mode fails, offer two options. Quit or run in a window
236             if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use"
237                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
238             {
239                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
240             }
241             else {
242                 // Pop up a message box letting user know the programe is closing.
243                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
244                 return FALSE;                             // Exit and return FALSE
245             }
246         }
247     }
248 
249     if (fullscreen) {                                     // Are we still in fullscreen mode
250         
251         /*
252          *  If we are still in fullscreen mode we‘ll set the extended style to WS_EX_APPWINDOW, 
253          *  which force a top level window down to the taskbar once our window is visible. 
254          *  For the window style we‘ll create a WS_POPUP window. 
255          *  This type of window has no border around it, making it perfect for fullscreen mode.
256 
257          *  Finally, we disable the mouse pointer. If your program is not interactive, 
258          *  it‘s usually nice to disable the mouse pointer when in fullscreen mode. It‘s up to you though.
259          */
260         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
261         dwStyle = WS_POPUP;                               // Window style
262         ShowCursor(FALSE);                                // Hide mosue pointer 
263     }
264     else {
265 
266         /*
267          *  If we‘re using a window instead of fullscreen mode, 
268          *  we‘ll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 
269          *  For style we‘ll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 
270          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 
271          *  window menu, and minimize / maximize buttons.
272          */
273         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
274         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
275     }
276 
277     /*
278      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 
279      *  instead, the window will be made larger to account for the pixels needed to draw the window border. 
280      *  In fullscreen mode, this command has no effect.
281      */
282     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
283     
284     /*
285      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 
286      *  These styles prevent other windows from drawing over or into our OpenGL Window.
287      */
288     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
289         "OpenGL",                                         // Class name
290         title,                                            // Window title
291         WS_CLIPSIBLINGS |                                 // Requried window style
292         WS_CLIPCHILDREN |                                 // Requried window style
293         dwStyle,                                          // Select window style
294         0, 0,                                             // Window position
295         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
296         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
297         NULL,                                             // No parent window
298         NULL,                                             // No menu
299         hInstance,                                        // Instance
300         NULL)))                                           // Don‘t pass anything to WM_CREATE
301     {
302         KillGLWindow();                                   //Reset the display
303         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
304         return FALSE;                                     // Retrurn FALSE;
305     }
306 
307     /*
308      *  aside from the stencil buffer and the (slow) accumulation buffer
309      */
310     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be 
311     {
312         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
313         1,                                                // Version number
314         PFD_DRAW_TO_WINDOW |                              // Format must support window
315         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
316         PFD_DOUBLEBUFFER,                                 // Must support double buffer
317         PFD_TYPE_RGBA,                                    // Request an RGBA format
318         bits,                                             // Select our color depth
319         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
320         0,                                                // No alpha buffer
321         0,                                                // shift bit ignored
322         0,                                                // No accumulation buffer
323         0, 0, 0, 0,                                       // Accumulation bits ignored
324         16,                                               // 16Bits Z_Buffer (depth buffer)
325         0,                                                // No stencil buffer
326         0,                                                // No auxiliary buffer
327         PFD_MAIN_PLANE,                                   // Main drawing layer
328         0,                                                // Reserved
329         0, 0, 0                                           // Layer makes ignored
330     };
331 
332     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
333         KillGLWindow();                                   // Reset the display
334         MessageBox(NULL, "Can‘t create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
335         return FALSE;                                     // Return FALSE
336     }
337 
338     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
339         KillGLWindow();                                   // Reset the display
340         MessageBox(NULL, "Can‘t find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
341         return FALSE;                                     // Return FALSE;
342     }
343 
344     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
345         KillGLWindow();                                   // Reset the display
346         MessageBox(NULL, "Can‘t set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
347         return FALSE;                                     // Return FALSE;
348     }
349 
350     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
351         KillGLWindow();                                   // Reset the display
352         MessageBox(NULL, "Can‘t create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
353         return FALSE;                                     // Return FASLE;
354     }
355 
356     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
357         KillGLWindow();                                   // Reset the display
358         MessageBox(NULL, "Can‘t activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
359         return FALSE;                                     // Return FALSE    
360     }
361 
362     /*
363      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
364      */
365     ShowWindow(hWnd, SW_SHOW);                            // Show the window
366     SetForegroundWindow(hWnd);                            // slightly higher priority
367     SetFocus(hWnd);                                       // Sets keyboard focus to the window
368     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
369 
370     /*
371      *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
372      */
373     if (!InitGL()) {                                      // Initialize our newly created GL window
374         KillGLWindow();                                   // Reset the display
375         MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
376         return FALSE;                                     // Return FALSE
377     }
378     return TRUE;
379 }
380     
381 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
382     UINT uMsg,                                            // Message for this window
383     WPARAM wParam,                                        // Additional message information
384     LPARAM lParam)                                        // Additional message information
385 {
386     switch (uMsg) {                                       // Check for window message
387         case WM_ACTIVATE: {                               // Check minimization state
388             if (!HIWORD(wParam)) {
389                 active = TRUE;                            // Program is active
390             }
391             else {
392                 active = FALSE;                           // Program is no longer active
393             }
394             return 0;                                     // Return to the message loop
395         }
396         case WM_SYSCOMMAND: {                             // Intercept system commands
397             switch (wParam) {                             // Check system calls
398                 case SC_SCREENSAVE:                       // Screensaver trying to start
399                 case SC_MONITORPOWER:                     // Monitor trying to enter powersave
400                 return 0;                                 // Prevent form happening
401             }
402             break;                                        // Exit
403         }
404         case WM_CLOSE: {                                  // Did we receive a close message
405             PostQuitMessage(0);                           // Send a quit message
406             return 0;
407         }
408         case WM_KEYDOWN: {                                // Is a key being held down
409             keys[wParam] = TRUE;                          // if so, mark it as TRUE

以上是关于OpenGL窗口的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 着色器编译但窗口中未出现渲染

OpenGL:基本图形绘画二

OpenGL ES之“深度测试”与“模板测试”的使用流程

OpenGL片段着色器不照亮场景

GPU如何渲染到正确的窗口?

片段着色器中未使用纹理数据 - OpenGL