windows設置opengl上下文

一、     設置像素格式

像素格式用於指定OpenGL繪畫的一些屬性,在windows中,使用PIXELFORMATDESCRIPTOR結構體來描述。一個設備可以支持許多像素格式,但只能擁有一種當前像素格式,需要從這一系列的像素格式中選擇出一種合適的像素格式來,並設置它。主要屬性有:

  •  像素緩衝是單緩衝還是雙緩衝;
  •  像素數據時RGBA還是顏色索引;
  •  顏色數據的位數;
  •  深度緩衝的位數;
  •  模板緩衝的位數;
  •  層的數量;
  •  各種可視化掩膜;

 

代碼片段如下:

1.1  填寫PIXELFORMATDESCRIPTOR結構體

  1. static PIXELFORMATDESCRIPTOR pfd=   {  
  2.     sizeof(PIXELFORMATDESCRIPTOR),  // Size Of This Pixel Format Descriptor  
  3.     1,                              // Version Number  
  4.     PFD_DRAW_TO_WINDOW |            // Format Must Support Window  
  5.     PFD_SUPPORT_OPENGL |            // Format Must Support OpenGL  
  6.     PFD_DOUBLEBUFFER,               // Must Support Double Buffering  
  7.     PFD_TYPE_RGBA,                  // Request An RGBA Format  
  8.     bits,                           // Select Our Color Depth  
  9.     0, 0, 0, 0, 0, 0,               // Color Bits Ignored  
  10.     0,                              // No Alpha Buffer  
  11.     0,                              // Shift Bit Ignored  
  12.     0,                              // No Accumulation Buffer  
  13.     0, 0, 0, 0,                     // Accumulation Bits Ignored  
  14.     16,                             // 16Bit Z-Buffer (Depth Buffer)    
  15.     0,                              // No Stencil Buffer  
  16.     0,                              // No Auxiliary Buffer  
  17.     PFD_MAIN_PLANE,                 // Main Drawing Layer  
  18.     0,                              // Reserved  
  19.     0, 0, 0                         // Layer Masks Ignored  
  20. };  


 

1.2  選擇合適的像素格式

  1. // get the best available match of pixel format for the device context  
  2. int  iPixelFormat = ChoosePixelFormat(hdc, &pfd);  
  3.   
  4. if(0 == iPixelFormat)  
  5. {  
  6.     cerr << "Choose pixel format failed." << endl;  
  7.     ...  
  8. }  


 

1.3  設置像素格式

  1. // make that the pixel format of the device context  
  2. if(!SetPixelFormat(hdc, iPixelFormat, &pfd))  
  3. {  
  4.     cerr << "Set pixel format failed." << endl;  
  5.     ...  
  6. }  


 

注意:必須在創建渲染上下文前設置像素格式。

參考http://msdn.microsoft.com/en-us/library/dd368832%28v=vs.85%29

二、     創建OpenGL渲染上下文(rendering context)

每一個調用了OpenGL API的線程都必須要有一個OpenGL渲染上下文,這個渲染上下文用來將OpenGL鏈接到Windwos的窗口系統。

一個線程只能有一個當前渲染上下文,一個渲染上下文只能最爲一個線程的當前上下文。如果調用OpenGL API的線程缺少當前渲染上下文,則不會有任何結果產生

2.1  創建OpenGL上下文

  1. HGLRC hglrc = wglCreateContext(hdc);  
  2.   
  3. if(!hglrc)  
  4. {  
  5.     cerr << "Create render contex failed." << endl;  
  6. …  
  7. }  


 

2.2  將OpenGL上下文設置爲當前線程的當前上下文

  1. if(!wglMakeCurrent(hdc, hglrc))  
  2. {  
  3.     cerr << "Make current rendering context failed." << endl;  
  4.     …  
  5. }  


 

如果要清除當前上下文,可以將wglMakeCurrent中的參數設置爲NULL即可。

注意:參數hdc必須和設置像素格式時使用的是同一個hdc

參考http://msdn.microsoft.com/en-us/library/dd369038%28v=vs.85%29

三、     顯示OpenGL渲染內容

當前面兩個步驟完成後,就可以使用OpenGL API進行渲染了。這時不再關注具體的渲染上下文,只需調用OpenGL的相應API即可。待渲染完畢,下一步要做的時就是要把它顯示在窗口環境中。因爲Windows下的設備環境使用了雙緩衝的機制,所以這裏就需要交換這兩個緩衝,即可將渲染的內容顯示在窗口中了。具體代碼如下:

  1. SwapBuffers(hdc);   // hdc需和前面兩個步驟中的hdc相同  


 

四、     銷燬OpenGL上下文

當我們不再進行OpenGL渲染的時候,就可以將OpenGL上下文銷燬了。具體代碼如下:

  1. if (hglrc)     // Do We Have A Rendering Context?  
  2. {  
  3.     // Are We Able To Release The DC And RC Contexts?  
  4.     if (!wglMakeCurrent(NULL,NULL))   
  5. {  
  6.         cerr << “Release HGLRC failed.” << endl;  
  7.     }  
  8.   
  9.     if (!wglDeleteContext(hglrc))  // Are We Able To Delete The HGLRC?  
  10.     {  
  11.         cerr << "Release Rendering Context Failed.” << endl;  
  12.     }  
  13.     hglrc =NULL;     // Set RC To NULL  
  14. }  


 

附錄

I.        創建窗口

前面說到那麼多,但都沒有說到如何創建顯示OpenGL渲染內容的窗口,下面接着說一下如何創建一個Windows窗口吧。具體代碼如下:

    1)註冊WNDCLASS類(結構體)

  1. WNDCLASS    wc; // Windows Class Structure  
  2.   
  3. hInstance = GetModuleHandle(NULL);  // Grab An Instance For Our Window  
  4. // Redraw On Size, And Own DC For Window.  
  5. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    
  6. wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages  
  7. wc.cbClsExtra  = 0;                    // No Extra Window Data  
  8. wc.cbWndExtra  = 0;                    // No Extra Window Data  
  9. wc.hInstance   = hInstance;           // Set The Instance  
  10. wc.hIcon       = LoadIcon(NULL, IDI_WINLOGO);    // Load The Default Icon  
  11. wc.hCursor    = LoadCursor(NULL, IDC_ARROW);   // Load The Arrow Pointer  
  12. wc.hbrBackground    = NULL;                     // No Background Required For GL  
  13. wc.lpszMenuName     = NULL;                     // We Don't Want A Menu  
  14. wc.lpszClassName    = "OpenGL";                 // Set The Class Name  
  15.   
  16. if (!RegisterClass(&wc)) // Attempt To Register The Window Class  
  17. {  
  18. cerr << “Failed to register the window.” << endl;  
  19. …  
  20. }  


    2)創建窗口

  1. HWND hWnd = CreateWindow("OpenGL""Hello World.",   
  2. WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW,  
  3.                   0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);  
  4. if(!hWnd)  
  5. {  
  6.    cerr << “Create window failed.” << endl;  
  7.    …  
  8. }  
  9.   
  10. ShowWindow(hWnd, SW_SHOW);  


 

Ⅱ.        銷燬窗口

當不再需要該窗口時,需要對其進行銷燬,步驟如下:

  1. if (hdc && !ReleaseDC(hWnd,hdc)) // Are We Able To Release The DC  
  2. {  
  3.     cerr << "Release Device Context Failed." << endl;  
  4.     hdc = NULL; // Set DC To NULL  
  5. }  
  6.   
  7. if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?  
  8. {  
  9.     cerr << "Could Not Release hWnd." << endl;  
  10.     hWnd=NULL; // Set hWnd To NULL  
  11. }  
  12.   
  13. if (!UnregisterClass("OpenGL",hInstance))   // Are We Able To Unregister Class  
  14. {  
  15.     cerr << "Could Not Unregister Class." << endl;  
  16.     hInstance=NULL; // Set hInstance To NULL  
  17. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章