什么是 OpenGL loading?linux
OpenGL是一份API规范,并非一个库。记住这点很是重要!它意味着每个API背后的具体实现都依赖于你的GPU硬件、操做系统以及显卡驱动。git
OpenGL规范定义了不少不一样的函数,而且规范会按期进行更新,你的显卡驱动可能不会支持所有的函数。你的显卡和显卡驱动的能力决定了你能使用的API规范的子集。这也是不把全部的OpenGL函数静态定义在一个头文件中供你使用的缘由。并且,将全部函数静态连接成一个库也是不可能的,由于你的应用运行的目标机器上会有各类各样不一样的OpenGL实现。github
在Windows机器上,OpenGL是以dll的方式实现的。在64位Windows操做系统上,64位的dll库位于 C:\Windows\system32\opengl32.dll,这个dll是显卡驱动的一部分,是随着显卡驱动一块儿发布的。windows
再次强调,大部分的OpenGL函数是不能被定义在某个标准的头文件中,而后静态连接进你的应用程序的。这也是为何OpenGL函数不能直接被调用,而须要显式的声明和加载。api
什么是 GLEW?ide
GLEW(OpenGL Extension Wrangler)是一个跨平台的用于OpenGL函数声明和加载的库,它一样具有在运行时检查目标机器是否支持某个OpenGL profile(一个profile就是一份指定配置支持的特定的OpenGL函数集)的能力。函数
GLEW很是的简单,尤为是针对刚开始接触OpenGL的新手。它把全部的脏活累活都替你作了,你能够在你的系统上自由的调用全部支持的有效OpenGL函数。ui
在StackOverflow上,全部关于OpenGL loading的问题下,都有人建议你使用OpenGL Loading Library,中止本身定制OpenGL loading去使用GLEW。甚至OpenGL官方的wiki都强烈建议你使用OpenGL loading library。this
可是像GLEW这样的OpenGL loading library有它们本身的缺点,下面就以GLEW为例,来详细讲下这些缺点spa
为何你最好不使用GLEW?
你能够用如下两种方式使用GLEW库:
如何定制本身的OpenGL Loader?
github上有不少自定义的OpenGL loader,其中不乏短小精干,很是好用的库,好比https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a,在这个的基础上,能够增长一些跨平台的宏定义。
#if defined(__linux__) #include <dlfcn.h> #define GLDECL // Empty define #define PAPAYA_GL_LIST_WIN32 // Empty define #endif // __linux__ #if defined(_WIN32) #include <windows.h> #define GLDECL WINAPI #define GL_ARRAY_BUFFER 0x8892 #define GL_ARRAY_BUFFER_BINDING 0x8894 ... typedef char GLchar; typedef ptrdiff_t GLintptr; typedef ptrdiff_t GLsizeiptr; #define PAPAYA_GL_LIST_WIN32 \ /* ret, name, params */ \ GLE(void, BlendEquation, GLenum mode) \ GLE(void, ActiveTexture, GLenum texture) \ /* end */ #endif // _WIN32
上面代码咱们首先包含不一样平台的动态库调用的头文件。而后定义了windows平台下的函数调用规范的宏GLDECL。咱们还须要包含GL/gl.h的头文件,可是这个文件在Linux和Windows上是不一样的。Windows SDK包含的gl.h版本是很是老的(OpenGL 1.1),因此它并无包含全部的OpenGL typedef,常量以及函数声明,可是Linux平台上通常是最新的。因此在Windows系统上须要手动添加这些定义。你能够直接包含这个文件https://www.khronos.org/registry/OpenGL/api/GL/glext.h,它包含这些常量和函数的定义。
最后就是定义你须要的函数了,代码以下:
#define BINKGL_LIST \ /* ret, name, params */ \ GLE(void, LinkProgram, GLuint program) \ GLE(void, GetProgramiv, GLuint program, GLenum pname, GLint *params) \ GLE(GLuint, CreateShader, GLenum type) \ GLE(void, ShaderSource, GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length) \ GLE(void, CompileShader, GLuint shader) \ GLE(void, GetShaderiv, GLuint shader, GLenum pname, GLint *params) \ GLE(void, GetShaderInfoLog, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) \ GLE(void, DeleteShader, GLuint shader) \ GLE(GLuint, CreateProgram, void) \ GLE(void, AttachShader, GLuint program, GLuint shader) \ GLE(void, DetachShader, GLuint program, GLuint shader) \ GLE(void, UseProgram, GLuint program) \ GLE(void, DeleteProgram, GLuint program) \ GLE(void, GenVertexArrays, GLsizei n, GLuint *arrays) \ GLE(void, BindVertexArray, GLuint array) \ GLE(void, BufferData, GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) \ GLE(void, GenBuffers, GLsizei n, GLuint *buffers) \ GLE(void, BindBuffer, GLenum target, GLuint buffer) \ GLE(void, DeleteBuffers, GLsizei n, const GLuint *buffers) \ GLE(void, TexParameteri, GLenum target, GLenum pname, GLint param) \ GLE(void, ActiveTexture, GLenum texture) \ GLE(void, BindAttribLocation, GLuint program, GLuint index, const GLchar *name) \ GLE(GLint, GetUniformLocation, GLuint program, const GLchar *name) \ GLE(void, Uniform4f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) \ GLE(void, Uniform4fv, GLint location, GLsizei count, const GLfloat *value) \ GLE(void, DeleteVertexArrays, GLsizei n, const GLuint *arrays) \ GLE(void, EnableVertexAttribArray, GLuint index) \ GLE(void, VertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) \ GLE(void, Uniform1i, GLint location, GLint v0) \ /* end */ #define GLE(ret, name, ...) typedef ret GLDECL name##proc(__VA_ARGS__); static name##proc * gl##name; BINKGL_LIST #undef GLE static void *GLhandle; bool gl_lite_init() { #if defined(__linux__) void* libGL = dlopen("libGL.so", RTLD_LAZY); if (!libGL) { printf("ERROR: libGL.so couldn't be loaded\n"); return false; } #define GLE(ret, name, ...) \ gl##name = (name##proc *) dlsym(libGL, "gl" #name); \ if (!gl##name) { \ printf("Function gl" #name " couldn't be loaded from libGL.so\n"); \ return false; \ } BINKGL_LIST #undef GLE #elif defined(_WIN32) HINSTANCE dll = LoadLibraryA("opengl32.dll"); typedef PROC WINAPI wglGetProcAddressproc(LPCSTR lpszProc); if (!dll) { OutputDebugStringA("opengl32.dll not found.\n"); return false; } wglGetProcAddressproc* wglGetProcAddress = (wglGetProcAddressproc*)GetProcAddress(dll, "wglGetProcAddress"); #define GLE(ret, name, ...) \ gl##name = (name##proc *)wglGetProcAddress("gl" #name); \ if (!gl##name) { \ OutputDebugStringA("Function gl" #name " couldn't be loaded from opengl32.dll\n"); \ return false; \ } BINKGL_LIST #undef GLE #else #error "GL loading for this platform is not implemented yet." #endif return true; }