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窗口的主要内容,如果未能解决你的问题,请参考以下文章