这里不是比较
GLAD和GLEW优劣问题,而是简单地说一下其实现流程。
GLAD
- 因为 - OpenGL只是一个 标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于- OpenGL驱动版本众多,大多数函数的位置(内存地址)都无法在 编译 时确定下来,需要在 运行时 查询。所以开发者在开发使用- OpenGL时,需要在 运行时 获取函数的内存地址并将其保存在一个函数指针中供以后使用。取得地址的方法因平台而异,(Windows)大致流程 如下:- 1 
 2
 3
 4
 5
 6
 7- // 定义函数原型 
 typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
 // 找到正确的函数并赋值给函数指针
 GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
 // 现在函数可以被正常调用了
 GLuint buffer;
 glGenBuffers(1, &buffer);
- 然而写这些代码非常复杂,而且很繁琐,需要对每个可能使用的函数都要重复这个过程。不过 - GLAD的做过就是将上面的过程进行简化供开发者使用。
- 根据 - Load OpenGL FunctionsWiKi,- wglGetProcAddress在失败时返回- NULL,但一些实现将返回其他值。1,2和3,以及-1过程如下:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- 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;
 }
- 在 MacOSX 平台,在 OSX 10.2 后 - GL Fuction是 weak 链接,也就意味着可以直接调用它们,未实现的扩展将解析为- NULL。- Apple建议需要- getProcAddress功能的程序使用- NSSymbol直接查找函数指针。如下:- Listing C-1 : - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- #import <mach-o/dyld.h> 
 #import <stdlib.h>
 #import <string.h>
 void * MyNSGLGetProcAddress (const char *name)
 {
 NSSymbol symbol;
 char *symbolName;
 symbolName = malloc (strlen (name) + 2);
 strcpy(symbolName + 1, name);
 symbolName[0] = '_';
 symbol = NULL;
 if (NSIsSymbolNameDefined (symbolName))
 symbol = NSLookupAndBindSymbol (symbolName);
 free (symbolName);
 return symbol ? NSAddressOfSymbol (symbol) : NULL;
 }
- Listing C-2: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31- #import "MyNSGLGetProcAddress.h" 
 static void InitEntryPoints (void);
 static void DeallocEntryPoints (void);
 
 // Function pointer type definitions
 typedef void (*glBlendColorProcPtr)(GLclampf red,GLclampf green,
 GLclampf blue,GLclampf alpha);
 typedef void (*glBlendEquationProcPtr)(GLenum mode);
 typedef void (*glDrawRangeElementsProcPtr)(GLenum mode, GLuint start,
 GLuint end,GLsizei count,GLenum type,const GLvoid *indices);
 
 glBlendColorProcPtr pfglBlendColor = NULL;
 glBlendEquationProcPtr pfglBlendEquation = NULL;
 glDrawRangeElementsProcPtr pfglDrawRangeElements = NULL;
 
 static void InitEntryPoints (void)
 {
 pfglBlendColor = (glBlendColorProcPtr) MyNSGLGetProcAddress
 ("glBlendColor");
 pfglBlendEquation = (glBlendEquationProcPtr)MyNSGLGetProcAddress
 ("glBlendEquation");
 pfglDrawRangeElements = (glDrawRangeElementsProcPtr)MyNSGLGetProcAddress
 ("glDrawRangeElements");
 }
 // -------------------------
 static void DeallocEntryPoints (void)
 {
 pfglBlendColor = NULL;
 pfglBlendEquation = NULL;
 pfglDrawRangeElements = NULL;;
 }
- 关于以上代码的解释,可以到这里查看。 
 
- 再回到 - GLAD,- 在 glad.h 文件可以看到 - glGenBuffers的定义:- 1 
 2
 3
 4
 5
 6
 7
 8
 9- #ifndef APIENTRYP 
 #define APIENTRYP APIENTRY *
 #endif
 define GLAPI extern
 typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers);
 GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
 #define glDeleteBuffers glad_glDeleteBuffers 
- 在 glad.c 文件中可以看到 - gladGetProcAddressPtr的定义:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35- #ifndef __APPLE__ 
 typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
 static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
 #endif
 static
 int open_gl(void) {
 #ifdef __APPLE__
 static const char *NAMES[] = {
 "../Frameworks/OpenGL.framework/OpenGL",
 "/Library/Frameworks/OpenGL.framework/OpenGL",
 "/System/Library/Frameworks/OpenGL.framework/OpenGL",
 "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
 };
 #else
 static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
 #endif
 unsigned int index = 0;
 for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
 libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
 if(libGL != NULL) {
 #ifdef __APPLE__
 return 1;
 #else
 gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
 "glXGetProcAddressARB");
 return gladGetProcAddressPtr != NULL;
 #endif
 }
 }
 return 0;
 }
 
GLEW
- GLEW的出现也是为了在开发时,能够针对不能显卡制造商的显卡的- OpenGL的不同版本,实现在 运行时 获取函数的内存地址并将其保存在一个函数指针中供以使用。
- 在 glew.h 文件中可以看懂 - glGenBuffers的定义:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- #ifndef GLEW_GET_FUN 
 #define GLEW_GET_FUN(x) x
 #endif
 #ifndef GLAPIENTRY
 #define GLAPIENTRY
 #endif
 typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers);
 GLEW_FUN_EXPORT PFNGLGENBUFFERSPROC __glewGenBuffers;
 #define glGenBuffers GLEW_GET_FUN(__glewGenBuffers) - 小结- GLAD和- GLEW的作用都是帮助在开发- OpenGL时简化其在 运行时 获取函数的内存地址并将其保存在一个函数指针中供以使用的流程。
 
        