加载OpenGL函数是创建OpenGL上下文后的一项重要的初始化工作,需要使用平台特定的函数查询函数指针,且不同的版本有不同的语义。
获取平台特定的OpenGL函数
1.Window
我们使用 wglGetProcAddress 来查询函数指针,该函数接收一个ASCII字符串的函数名作为参数,可以查询 OpenGL 函数 和 平台特定的WGL函数,这个函数只能在有效的上下文(OpenGL context) 上才能执行,返回的函数指针也是上下文相关的。Windows 文档指出查询出的函数可以在其它的OpenGL上下文中执行,这取决于该上下文的厂商和像素格式。
在实际运用中,如果两个OpenGL上下文同时来源一个厂商和同一个GPU(对单机单显卡用户多是如此情况),查询出的函数指针可以共用。这在Windows 创建上下文时比较重要,比如我们可以预先创建一个上下文来获得这些函数指针,随后在其它的OpenGL上下文中使用这些函数,它简化了上下文的初始化过程。
根据MSDN 文档中的说明,wglGetProcAddress 可以返回 NULL, 1, 2, 3, -1 这些值来作为查询失败的结果。
使用wglGetProcAddress() 是查询不到OpenGL32.DLL 中导出的函数,这就意味着OpenGL Ver1.1 的旧函数不能够被查询到,它只能查询OpenGL Ver1.1之后的扩展函数。Win32 函数GetProcAddress()可以获取 OpenGL32.DLL 中的导出函数。这两个函数互相配合使用,可以获取OpenGL 所有函数指针。
void *GetAnyGLFuncAddress(const char *name)
{
void *p = (void *)wglGetProcAddress(name);
if(p == 0 ||
(p == (void*)0x1) || (p == (void*)0x2) || (p == (void*)0x3) ||
(p == (void*)-1) )
{
HMODULE module = LoadLibraryA("opengl32.dll");
p = (void *)GetProcAddress(module, name);
}
return p;
}
2.Linux and X-Windows
在 Linux 的 X-Windows系统中,使用 glxGetProcAddress() 函数来获取OpenGL 函数指针,也是使用 ASCII 字符串作为函数名参数。该函数可以在没有上下文的情况下使用,但返回的函数显然不能任意使用,因为返回的函数是与OpenGL 上下文相关的,具有一定的“语境”。这使得在具体的OpenGL上下文下获取特定的函数指针变得困难,我们只有使用OpenGL 标准的扩展查询方式获取当前OpenGL上下文中的具体函数。
函数类型
每个查询到的OpenGL函数指针都有对应的c语言形式的函数类型,它们具有不同的返回值和参数列表。OpenGL Registry 在glext.h 和 glcorearb.h 文件中提供了OpenGL Ver1.2 或以上版本的函数的类型。
例如定义的函数类型:
typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
可以用该函数类型定义函数名。
PFNGLUSEPROGRAMPROC glUseProgram;
检索函数
在OpenGL3.0 之前,我们可以使用 glGetString(GL_VERSION) 获取指定OpenGL 版本的扩展字符串,再对字符串解析, 使用查询函数获取该版本下的所有的函数指针。
OpenGL3.0 以后的版本,可以先用 glGetIntergerv(GL_MAJOR_VERSION) 或 glGetIntergerv(GL_MINOR_VERSION) 查询是否支持创建特定版本的OpenGL上下文。
OpenGL3.0版本后,先用 glGetIntegerv(GL_NUM_EXTENSIONS) 获取OpenGL扩展函数的数目,再用glGetStringi() 函数来获取扩展函数名。这比直接使用 glGetString()函数更安全,因为我们并不知道该分配多大的缓冲区来存储包括所有扩展函数名字的字符串,如果分配的缓冲区的大小与查询的扩展函数名字符串的大小不匹配时,容易造成程序崩溃。
Window 查询OpenGL API
查询WGL extensions 之前, 必须先创建 OpenGL Context, 然后make it current, 再通过wglGetProcAddress获取OpenGL 函数指针。

1261

被折叠的 条评论
为什么被折叠?



