我有一个关于如何(正确)使用的问题glewInit().
假设我有一个多窗口应用程序,我应该glewInit()在应用程序(即全局)级别调用一次吗?或调用glewInit()每个窗口(即每个OpenGL渲染上下文)?
dat*_*olf 10
根据所使用的GLEW构建,水密方法是glewInit在每次上下文更改后调用!
使用X11/GLX函数指针是不变的.
但在Windows OpenGL中,函数指针特定于每个上下文.GLEW的一些版本是多上下文感知的,而其他版本则不是.因此,为了涵盖这种情况,从技术上讲,每次上下文确实发生变化时,您都必须调用它.
(编辑:由于要求澄清)
对于每个窗口(即每个OpenGL渲染上下文)?
首先要做的事情是:OpenGL上下文与Windows无关.拥有一个窗口但有多个渲染上下文是完全没问题的.在Microsoft Windows中,对OpenGL重要的是与窗口关联的设备上下文(DC).但它也可以反过来:你可以有一个OpenGL上下文,但是有多个窗口使用它(只要窗口的pixelformat与OpenGL上下文兼容).
所以这是合法的:
HWND wnd = create_a window()
HDC dc = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc, pf);
HGLRC rc0 = create_opengl_context(dc);
HGLRC rc1 = create_opengl_context(dc);
wglMakeCurrent(dc, rc0);
draw_stuff(); // uses rc0
wglMakeCurrent(dc, rc1);
draw_stuff(); // uses rc1
Run Code Online (Sandbox Code Playgroud)
这也是如此
HWND wnd0 = create_a window()
HDC dc0 = GetDC(wnd)
HWND wnd1 = create_a window()
HDC dc1 = GetDC(wnd)
PIXELFORMATDESCRIPTOR pf = select_pixelformat();
SetPixelFormat(dc0, pf);
SetPixelFormat(dc1, pf);
HGLRC rc = create_opengl_context(dc0); // works also with dc1
wglMakeCurrent(dc0, rc);
draw_stuff();
wglMakeCurrent(dc1, rc);
draw_stuff();
Run Code Online (Sandbox Code Playgroud)
这是扩展进入图片的地方.类似的功能glActiveTexture不是OpenGL规范的一部分,它已被固定到Windows应用程序二进制接口(ABI)中.因此,您必须在运行时获取指向它的函数指针.这就是GLEW所做的.在内部它看起来像这样:
首先,它定义函数指针的类型,将它们声明为外部变量,并使用一些预处理器魔法来避免命名空间冲突.
typedef void (*PFNGLACTIVETEXTURE)(GLenum);
extern PFNGLACTIVETEXTURE glew_ActiveTexture;
#define glActiveTexture glew_ActiveTexture;
Run Code Online (Sandbox Code Playgroud)
在glewInit函数指针中,变量设置为使用获得的值wglGetProcAddress(为了便于阅读,我省略了类型转换).
int glewInit(void)
{
/* ... */
if( openglsupport >= gl1_2 ) {
/* ... */
glew_ActiveTexture = wglGetProcAddress("glActiveTexture");
/* ... */
}
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
现在重要的部分:wglGetProcAddress使用OpenGL渲染上下文,它在调用时是最新的.所以无论最后一次wglMakeCurrent电话会议是什么.如前所述,扩展函数指针与其OpenGL上下文相关联,并且不同的OpenGL上下文可以为同一函数提供不同的函数指针.
所以,如果你这样做
wglMakeCurrent(…, rc0);
glewInit();
wglMakeCurrent(…, rc1);
glActiveTexture(…);
Run Code Online (Sandbox Code Playgroud)
它可能会失败.所以一般来说,对于GLEW,每次调用wglMakeCurrent必须立即跟随a glewInit.GLEW的一些版本是多上下文感知的并且在内部执行此操作.其他人不是.但是,glewInit多次呼叫是完全安全的,所以安全的方法是调用它,只是为了确定.