windows设置opengl上下文

本文详细介绍了在Windows环境下使用OpenGL进行渲染的基本步骤,包括设置像素格式、创建渲染上下文、显示渲染内容及销毁上下文等过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、     设置像素格式

像素格式用于指定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. }  
OpenGL上下文OpenGL Context)是OpenGL中一个核心概念,用于封装所有与OpenGL相关的状态、对象和资源。每个OpenGL上下文包含完整的渲染状态,包括但不限于当前绑定的缓冲区、纹理、着色器程序、顶点数组对象(VAO)、帧缓冲区等。上下文的作用是为应用程序提供一个独立的环境,以便进行图形渲染操作。 OpenGL上下文的一个关键特性是线程绑定性。在大多数平台上,一个OpenGL上下文只能在创建它的线程上使用,这意味着所有与该上下文相关的OpenGL调用必须在该线程上执行。这种设计确保了上下文内部状态的一致性和线程安全性。 在多线程环境中,应用程序可能需要在不同的线程之间切换OpenGL上下文。这种切换通常涉及到将当前线程的上下文与某个线程解绑,并将另一个上下文绑定到该线程上。上下文切换对于实现高效的图形渲染和资源共享至关重要,尤其是在涉及多个渲染线程或多窗口应用程序的情况下。 此外,OpenGL上下文还支持共享资源的功能。通过上下文共享机制,多个上下文可以访问相同的纹理、缓冲区等资源,这在实现复杂的图形应用程序时非常有用。共享资源机制允许在不同的上下文之间高效地传递数据,而无需进行额外的复制操作。 在实际应用中,例如在浏览器或复杂的图形引擎中,可能会存在多个OpenGL上下文,每个上下文可能对应不同的渲染目标或不同的线程。为了有效地管理这些上下文,通常会有一个上下文调度器负责协调上下文之间的切换和资源共享[^1]。 ### OpenGL上下文切换的示例代码 以下是一个简单的示例,展示如何在Windows平台上使用WGL(Windows GL)API进行OpenGL上下文的创建和切换: ```c #include <windows.h> #include <GL/gl.h> // 创建窗口并获取设备上下文 HWND hwnd = CreateWindow(...); HDC hdc = GetDC(hwnd); // 设置像素格式 PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; int pixelFormat = ChoosePixelFormat(hdc, &pfd); SetPixelFormat(hdc, pixelFormat, &pfd); // 创建并激活第一个OpenGL上下文 HGLRC hglrc1 = wglCreateContext(hdc); wglMakeCurrent(hdc, hglrc1); // 在第一个上下文中执行一些操作 glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // 设置清屏颜色为红色 glClear(GL_COLOR_BUFFER_BIT); SwapBuffers(hdc); // 创建并激活第二个OpenGL上下文 HGLRC hglrc2 = wglCreateContext(hdc); wglMakeCurrent(hdc, hglrc2); // 在第二个上下文中执行一些操作 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // 设置清屏颜色为绿色 glClear(GL_COLOR_BUFFER_BIT); SwapBuffers(hdc); // 恢复使用第一个上下文 wglMakeCurrent(hdc, hglrc1); // 清理资源 wglDeleteContext(hglrc1); wglDeleteContext(hglrc2); ReleaseDC(hwnd, hdc); ``` 在上述代码中,首先创建了一个窗口并获取了设备上下文(HDC)。接着设置了像素格式,并创建了两个OpenGL上下文。通过调用`wglMakeCurrent`函数,可以在不同的上下文之间切换。每个上下文执行了不同的清屏操作,展示了如何在不同的上下文设置不同的渲染状态。 ### 总结 OpenGL上下文OpenGL渲染的核心,它不仅封装了所有渲染状态,还提供了线程绑定性和资源共享的能力。通过合理管理和切换上下文,应用程序可以实现高效的图形渲染和复杂的多线程图形处理任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值