如何使用OpenGL在windows上的同一应用程序中在两个单独的3D窗口内绘制? 我在Windows上的C++中实现了一个第三方程序的插件。
第三方程序有一个使用OpenGL显示3D图形的窗口。 但是,我需要该插件来创建另一个窗口,该窗口也使用OpenGL显示3D图形 我是否需要为我的窗口创建新的OpenGL渲染上下文,或者是否有某种方法可以“重用”第三方程序使用的OpenGL渲染上下文? 我假设我必须创建一个新的OpenGL渲染上下文,并尝试了以下操作:如何使用OpenGL在windows上的同一应用程序中在两个单独的3D窗口内绘制? 我在Windows上的C++中实现了一个第三方程序的插件。,c++,windows,multithreading,winapi,opengl,C++,Windows,Multithreading,Winapi,Opengl,第三方程序有一个使用OpenGL显示3D图形的窗口。 但是,我需要该插件来创建另一个窗口,该窗口也使用OpenGL显示3D图形 我是否需要为我的窗口创建新的OpenGL渲染上下文,或者是否有某种方法可以“重用”第三方程序使用的OpenGL渲染上下文? 我假设我必须创建一个新的OpenGL渲染上下文,并尝试了以下操作: // create a rendering context hglrc = wglCreateContext (hdc); // make it the calling t
// create a rendering context
hglrc = wglCreateContext (hdc);
// make it the calling thread's current rendering context
wglMakeCurrent (hdc, hglrc);
但是,最后一个函数失败了。
我注意到
一个线程可以有一个当前呈现上下文。一个进程可以通过多线程具有多个呈现上下文
这是否意味着我的窗口需要在独立于第三方程序的线程中运行?您没有发布由wglMakeCurrent()生成的错误代码,因此我不会猜测原因。然而,这不是绑定本身。句子“一个线程可以有一个当前呈现上下文”意味着新上下文将“替换”旧上下文并成为当前上下文。我不知道为什么要将两个上下文设置为当前上下文(或运行另一个线程),但这不是解决方法。除非绝对必要,否则在渲染时避免使用多线程。 那么,回答你的问题: 是的,您可以“重用”OpenGL渲染上下文 你可能会问,为什么?渲染上下文是为特定设备上下文(HDC)创建的,它是每个窗口(HWND)的专有属性!那这怎么可能呢 由于功能原型的原因,这似乎是不可能的: HWND my_window = CreateWindow(...); HDC my_dc = GetDC(my_new_window); //Setup pixel format for 'my_dc'... HGLRC my_rc = wglCreateContext(my_dc); wglMakeCurrent(my_dc, my_rc); HWND my_window=CreateWindow(…); HDC my_dc=GetDC(my_new_窗口); //设置“my_dc”的像素格式。。。 HGLRC my_rc=wglCreateContext(my_dc); wglMakeCurrent(my_dc,my_rc); 这确实让您认为呈现上下文绑定到此特定设备上下文,并且仅对其有效。但事实并非如此。 关键部分是注释(设置像素格式)。渲染上下文是为特定的DC类创建的,更精确地说,是为具有相同像素格式的DC创建的。因此,下面的代码完全有效: //window_1 = main window, window_2 = your window HDC dc_1 = GetDC(window_1); Set_pixel_format_for_dc_1(); //Usual stuff HGLRC rc = wglCreateContext(dc_1); wglMakeCurrent(dc_1, rc); ultra_super_draw(); //..... HDC dc_2 = GetDC(window_2); //Get dc_1's PF to make sure it's compatible with rc. int pf_index = GetPixelFormat(dc_1); PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); DescribePixelFormat(dc_1, pf_index, sizeof(PIXELFORMATDESCRIPTOR), &pfd); SetPixelFormat(dc_2, pf_index, &pfd); wglMakeCurrent(dc_2, rc); another_awesome_render(); wglMakeCurrent(NULL, NULL); //窗口1=主窗口,窗口2=您的窗口 HDC dc_1=GetDC(窗口_1); 为_dc_1()设置_像素_格式_//平常的东西 HGLRC=wglCreateContext(dc_1); wglMakeCurrent(dc_1,rc); ultra_super_draw(); //..... HDC dc_2=GetDC(窗口_2); //获取dc_1的PF,确保其与rc兼容。 int pf_index=GetPixelFormat(dc_1); 像素描述符pfd; 零内存(&pfd,sizeof(像素格式描述符)); 描述像素格式(dc_1、pf_索引、sizeof(像素格式描述符)和pfd); SetPixelFormat(dc_2、pf_索引和pfd); wglMakeCurrent(dc_2,rc); 另一个精彩的呈现(); wglMakeCurrent(NULL,NULL); 如果你仍然不相信,那么: wglMakeCurrent(hdc,hglrc):hdc参数必须引用OpenGL支持的图形表面。它不需要与创建hglrc时传递给wglCreateContext的hdc相同,但必须位于同一设备上,并且具有相同的像素格式 我想你已经熟悉这些电话了。现在,我不知道渲染必须满足哪些条件,但如果没有其他要求,我看不出这一点有任何困难: HDC my_dc = Create_my_DC(); //... void my_new_render { //Probably you want to save current binding: HDC current_dc = wglGetCurrentDC(); HGLRC current_context = wglGetCurrentContext(); wglMakeCurrent(my_dc, current_context); MyUltraSuperRender(...); wglMakeCurrent(current_dc, current_context); } HDC my_dc=创建我的dc(); //... 使我的新渲染无效 { //可能要保存当前绑定: HDC current_dc=wglGetCurrentDC(); HGLRC current_context=wglGetCurrentContext(); wglMakeCurrent(我的dc,当前上下文); MyUltraSuperRender(…); wglMakeCurrent(当前\u dc,当前\u上下文); }
希望这有帮助:)首先,您实际上应该为插件创建一个单独的OpenGL上下文,原因很简单,它为您提供了一个单独的状态空间,不会干扰主程序OpenGL上下文 但是,您误解了有关多个渲染上下文的部分。一个进程完全可能有任意数量的OpenGL上下文。但是进程的每个线程一次只能绑定一个上下文。该绑定还包括上下文绑定到的窗口DC。然而,随时更改上下文绑定是完全合法的。要么更改给定上下文绑定到的窗口,要么切换上下文,要么同时执行这两项操作 因此,在您的情况下,我建议您为插件创建一个自定义上下文,用于插件创建的所有窗口 简单上下文“创建”代码失败有一个简单的原因:您的窗口很可能没有设置像素格式描述符 我建议您使用以下方法创建新窗口和上下文:
/* first get hold of the HDC/HRC of the parent */
HDC parentDC = wglGetCurrentDC();
HRC parentRC = wglGetCurrentContext();
int pixelformatID = GetPixelFormat(parentDC);
/* we use the same PFD as the parent */
PIXELFORMATDESCRIPTOR pixelformat;
memset(pixelformat, 0, sizeof(pixelformat);
DescribePixelFormat(parentDC, pixelformatID, sizeof(pixelformat), &pixelformat);
/* create a window and set it's pixelformat to the parent one's */
HWND myWND = create_my_window();
HDC myDC = GetDC(myWND);
SetPixelFormat(myDC, pixelformatID, &pixelformat);
/* finally we can create a rendering context
* it doesn't matter if we create it against
* the parent or our own DC.
*/
HRC myRC = wglCreateContext(myDC);
/* we're done here... */
现在,每当插件想要呈现某个内容时,它都应该绑定自己的上下文,执行它的操作并绑定以前绑定的上下文:
HDC prevDC = wglGetCurrentDC();
HRC prevRC = wglGetCurrentContext();
wglMakeCurrent(myDC, myRC);
/* do OpenGL stuff */
wglMakeCurrent(prevDC, prevRC);
如果您的窗口与第三方应用程序的窗口具有相同的像素格式,则不需要单独的线程。告诉我们wglMakeCurrent()失败的确切程度可能会有所帮助。