为每个渲染上下文调用glewInit一次?或整个应用程序一次?

Cha*_*ang 9 opengl glew

我有一个关于如何(正确)使用的问题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多次呼叫是完全安全的,所以安全的方法是调用它,只是为了确定.