什么是 OpenGL loading?

OpenGL是一份API规范,并不是一个库。记住这点非常重要!它意味着每一个API背后的具体实现都依赖于你的GPU硬件、操作系统以及显卡驱动。

OpenGL规范定义了很多不同的函数,并且规范会定期进行更新,你的显卡驱动可能不会支持全部的函数。你的显卡和显卡驱动的能力决定了你能使用的API规范的子集。这也是不把所有的OpenGL函数静态定义在一个头文件中供你使用的原因。而且,将所有函数静态链接成一个库也是不可能的,因为你的应用运行的目标机器上会有各种各样不同的OpenGL实现。

在Windows机器上,OpenGL是以dll的方式实现的。在64位Windows操作系统上,64位的dll库位于 C:\Windows\system32\opengl32.dll,这个dll是显卡驱动的一部分,是随着显卡驱动一起发布的。

再次强调,大部分的OpenGL函数是不能被定义在某个标准的头文件中,然后静态链接进你的应用程序的。这也是为什么OpenGL函数不能直接被调用,而需要显式的声明和加载。

什么是 GLEW?

GLEW(OpenGL Extension Wrangler)是一个跨平台的用于OpenGL函数声明和加载的库,它同样具备在运行时检查目标机器是否支持某个OpenGL profile(一个profile就是一份指定配置支持的特定的OpenGL函数集)的能力。

GLEW非常的简单,尤其是针对刚开始接触OpenGL的新手。它把所有的脏活累活都替你做了,你可以在你的系统上自由的调用所有支持的有效OpenGL函数。

在StackOverflow上,所有关于OpenGL loading的问题下,都有人建议你使用OpenGL Loading Library,停止自己定制OpenGL loading去使用GLEW。甚至OpenGL官方的wiki都强烈建议你使用OpenGL loading library。

但是像GLEW这样的OpenGL loading library有它们自己的缺点,下面就以GLEW为例,来详细讲下这些缺点

为什么你最好不使用GLEW?

你可以用以下两种方式使用GLEW库:

  1. Dynamically linking动态链接:一个OpenGL应用或者引擎发布后,我们希望用户可以很方便地在他们的机器上进行构建,GLEW使用动态链接的话,我们要么为它要单独建立一个编译工程,要么我们自己要针对不同的目标机器,提前编译好各种不同机器上的dll或so库,这样可以说很麻烦
  2. Shipping the source连同代码一起发布:将GLEW库同OpenGL应用静态编译在一起,这种方式可以完美避开以上方式的缺点,唯一的缺点是GLEW库的代码量很大,它的存在增加了代码的复杂度,同时增加了代码的编译时间。GLEW如此庞大的原因是它维护了所有的OpenGL函数,而我们的应用可能只需要其中很小的一个子集,比如我们只需要modern opengl,也就是其core profile。

如何定制自己的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;
}

OpenGL Loading的更多相关文章

  1. OpenGL快问快答

    OpenGL快问快答 本文内容主要来自对(http://www.opengl.org/wiki/FAQ)的翻译,随机加入了本人的观点.与原文相比,章节未必完整,含义未必雷同,顺序未必一致.仅供参考. ...

  2. OpenGL ES 3.0: 图元重启(Primitive restart)

    [TOC] 背景概述 在OpenGL绘制图形时,可能需要绘制多个并不相连的图形.这样的情况下这几个图形没法被当做一个图形来处理.也就需要多次调用 DrawArrays 或 DrawElements. ...

  3. 【转】OpenGL多线程创建纹理,附加我的测试结果

    原文地址 http://www.cnblogs.com/mazhenyu/archive/2010/04/29/1724190.html 关于这个问题以前只知道多个线程不能同时使用一个RC,结果为了能 ...

  4. OpenGL超级宝典visual studio 2013开发环境配置,GLTools

    做三维重建需要用到OpenGL,开始看<OpenGL超级宝典>,新手第一步配置环境就折腾了一天,记录下环境的配置过程. <超级宝典>中的例子使用了GLEW,freeglut以及 ...

  5. OpenGL阴影,Shadow Volumes(附源程序,使用 VCGlib )

    实验平台:Win7,VS2010 先上结果截图:    本文是我前一篇博客:OpenGL阴影,Shadow Mapping(附源程序)的下篇,描述两个最常用的阴影技术中的第二个,Shadow Volu ...

  6. 【OpenGL】 第一篇 OpenGL概览

    ---------------------------------------------------------------------------------------------------- ...

  7. IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)

    在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...

  8. NeHe OpenGL教程 第四十五课:顶点缓存

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  9. OpenGL extension specification (from openGL.org)

    Shader read/write/atomic into UAV global memory (need manual sync) http://www.opengl.org/registry/sp ...

随机推荐

  1. Oracle Cannot Update TOP N Issue, 请专家解答

    大家好 上周写了匿名方法一文,很多读者,很高兴,相信我们已经从大伙的回复中,对.NET又有了更深刻的认识. 好,现在说主题,各类数据库都有相应更新本表top n的方案.现在我一一举例 首先看表结构如下 ...

  2. Jquery queue实例

    $(function () { var queueList = [ function () { $("div").animate({ height: 80, top: 40 }, ...

  3. 在iis7.5上部署asp.net mvc5

    部署mvc5跟部署mvc4是一样的,唯一不同的是需要修改一下web.config的配置 在web.config中加入一下节点即可 <system.webServer> <module ...

  4. web利用table表格生成excel格式问题

    当我们把web页面上的table导成excel形式时,有时候我们的数据需要以特定的格式呈现出来,这时候我们就需要给指定的单元格添加一些样式规格信息. 文本:vnd.ms-excel.numberfor ...

  5. 关于C#中Timer定时器的重入问题解决方法(也适用于多线程)

    项目中用到了定时器随着服务启动作定时任务,按指定的准点时间定时执行相关操作,但是在指定准点时间内我只想让它执行一次,要避免重入问题的发生. 首先简单介绍一下timer,这里所说的timer是指的Sys ...

  6. StringUtils常用方法介绍

    要使用StringUtils类,首先需要导入:import org.apache.commons.lang.StringUtils;这个包 在maven项目中需要添加下面这个依赖: <depen ...

  7. ios app提交之前需要哪几个证书

    1.遇到的问题 一款App在别人的机器上开发和发布,现在迭代更新和开发需要在一台新mac机上开发和发布. (使用同一个开发者账号)问题: 1.在新mac机器上开发并导入真机测试,是不是需要从别人的机器 ...

  8. 871. Minimum Number of Refueling Stops

    A car travels from a starting position to a destination which is target miles east of the starting p ...

  9. 自动备份数据库crond

    #!/bin/bash # export and backup the abgent_web database.sql mysqldump -uuser -ppassword ltden_db --s ...

  10. flink学习笔记-数据源(DataSource)

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...