Opengl入门

来源:互联网 发布:终极算法 豆瓣 编辑:程序博客网 时间:2024/04/30 11:43

OpenGL从推出到现在,已经有相当长的一段时间了。其间,OpenGL不断的得到更新。最新版的是4.3版本。

2.x增加顶点着色器,片段着色器

3.x增加FBO,几何着色器

4.x增加buffer, 镶嵌着色器

检查自己的OpenGL版本

可以很容易的知道自己系统中的OpenGL版本,方法就是调用glGetString函数。 

const char* version = (constchar*)glGetString(GL_VERSION);
printf("OpenGL 版本:%s\n", version);

glGetString(GL_VERSION);会返回一个表示版本的字符串,字符串的格式为X.X.X,就是三个整数,用小数点隔开,第一个数表示OpenGL主版本号,第二个数表示OpenGL次版本号,第三个数表示厂商发行代号。比如我在运行时得到的是"2.0.1",这表示我的OpenGL版本为2.0(主版本号为2,次版本号为0),是厂商的第一个发行版本。
通过sscanf函数,也可以把字符串分成三个整数,以便详细的进行判断。

int main_version, sub_version, release_version;
const char* version = (constchar*)glGetString(GL_VERSION);
sscanf(version, "%d.%d.%d", &main_version, &sub_version, &release_version);
printf("OpenGL 版本:%s\n", version);
printf("主版本号:%d\n", main_version);
printf("次版本号:%d\n", sub_version);
printf("发行版本号:%d\n", release_version);
glGetString还可以取得其它的字符串。
glGetString(GL_VENDOR); 返回OpenGL的提供厂商。
glGetString(GL_RENDERER); 返回执行OpenGL渲染的设备,通常就是显卡的名字。
glGetString(GL_EXTENSIONS); 返回所支持的所有扩展,每两个扩展之间用空格隔开。详细情况参见下面的关于“OpenGL扩展”的叙述。

OpenGL扩展
OpenGL版本的更新并不快。如果某种技术变得流行起来,但是OpenGL标准中又没有相关的规定对这种技术提供支持,那就只能通过扩展来实现了。
厂商在发行OpenGL时,除了遵照OpenGL标准,提供标准所规定的各种功能外,往往还提供其它一些额外的功能,这就是扩展。
扩展的存在,使得各种新的技术可以迅速的被应用到OpenGL中。比如“多重纹理”,它是在OpenGL 1.3中才被加入到标准中的,在OpenGL 1.3出现以前,很多OpenGL实现都通过扩展来支持“多重纹理”。这样,即使OpenGL版本不更新,只要增加新的扩展,也可以提供新的功能了。这也说明,即使OpenGL版本较低,也不一定不支持一些高版本OpenGL才提供的功能。实际上某些OpenGL 1.5的实现,也可能提供了最新的OpenGL 2.1版本所规定的大部分功能。
当然扩展也有缺点,那就是程序在运行的时候必须检查每个扩展功能是否被支持,导致编写程序代码复杂。

扩展的名字
每个OpenGL扩展,都必须向OpenGL的网站注册,确认后才能成为扩展。注册后的扩展有编号和名字。编号仅仅是一个序号,名字则与扩展所提供的功能相关。
名字用下划线分为三部分。举例来说,一个扩展的名字可能为:GL_NV_half_float,其意义如下:
第一部分为扩展的目标。比如GL表示这是一个OpenGL扩展。如果是WGL则表示这是一个针对Windows的OpenGL扩展,如果是GLX则表示这是一个针对linux的X Window系统的OpenGL扩展。
第二部分为提供扩展的厂商。比如NV表示这是nVidia公司所提供的扩展。相应的还有ATI, IBM, SGI, APPLE, MESA等。
剩下的部分就表示扩展所提供的内容了。比如half_float,表示半精度的浮点数,每个浮点数的精度只有单精度浮点数的一半,因此只需要两个字节就可以保存。这种扩展功能可以节省内存空间,也节省从内存到显卡的数据传输量,代价就是精确度有所降低。
EXT扩展和ARB扩展
最初的时候,每个厂商都提供自己的扩展。这样导致的结果就是,即使是提供相同的功能,不同的厂商却提供不同的扩展,这样在编写程序的时候,使用一种功能就需要依次检查每个可能支持这种功能的扩展,非常繁琐。
于是出现了EXT扩展和ARB扩展。
EXT扩展是由多个厂商共同协商后形成的扩展,在扩展名字中,“提供扩展的厂商”一栏将不再是具体的厂商名,而是EXT三个字母。比如GL_EXT_bgra,就是一个EXT扩展。
ARB扩展不仅是由多个厂商共同协商形成,还需要经过OpenGL体系结构审核委员会(即ARB)的确认。在扩展名字中,“提供扩展的厂商”一栏不再是具体的厂商名字,而是ARB三个字母。比如GL_ARB_imaging,就是一个ARB扩展。
通常,一种功能如果有多个厂商提出,则它成为EXT扩展。在以后的时间里,如果经过了ARB确认,则它成为ARB扩展。再往后,如果OpenGL的维护者认为这种功能需要加入到标准规定中,则它不再是扩展,而成为标准的一部分。
例如point_parameters,就是先有GL_EXT_point_parameters,再有GL_ARB_point_parameters,最后到OpenGL 1.4版本时,这个功能为标准规定必须提供的功能,不再是一个扩展。
在使用OpenGL所提供的功能时,应该按照标准功能、ARB扩展、EXT扩展、其它扩展这样的优先顺序。例如有ARB扩展支持这个功能时,就不使用EXT扩展。


glext; glew, glee这些library的原理

下面就是glext为我们做的事:

(1), 根据显卡厂商对某个extension的具体说明来定义一些宏.

#define GL_ARRAY_BUFFER_ARB 0x8892 //具体的地址是在各个specification中定义的.

#define GL_STATIC_DRAW_ARB 0x88E4

(2), 声明一些函数指针的类型.

typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);

typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);

typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);

typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);

然后在我自己的实现中就需要做以下的事:

(3). 声明定义一些函数指针:

PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;

PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;

PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;

PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;

(4). 利用wglGetProcAddress函数取得各个函数的地址指针.

glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");

glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");

glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");

而其实在glATI.h, wglATI.h, ATIExtensions.h, and ATIExtensions.c中也是这么做的.

那些glew, glee就将上面4步都给我们做了.

所以当使用extensions时候,

要么是下载glext回来,自己提供源代码实现(3, 4)两步.

要么是直接用glew or glee.


<GL/glext.h>:扩展头文件。因为微软公司对OpenGL的支持不太积极,VC系列编译器虽然有<GL/gl.h>这个头文件,但是里面只有OpenGL 1.1版本中所规定的内容,而没有OpenGL 1.2及其以后版本。对当前的计算机配置而言,几乎都支持OpenGL 1.4版本,更高的则到1.5, 2.0, 2.1,而VC无法直接使用这些功能。为了解决这一问题,就有了<GL/glext.h>头文件。这个头文件提供了高版本OpenGL所需要的各种常数声明以及函数指针声明。

GLee.h和glew.h都是windows平台下的GL扩展头文件,但是glew使用起来不是很好用,调试时经常会出现一些莫名奇妙的错误,于是有人写了一个轻量级的glew就是GLee。 使用glew时,有些扩展是需要获取指针的但有些不需要,因此最好在使用的时候都查询并获取要使用的GL函数或扩展,如果不获取有可能会出现内存异常。 GLee使用起来就相对方便的多了,只需要将GLee.c和GLee.h包含进工程,再在要使用GL函数或扩展的文件中Include上GLee.h就OK了,最重要的是不需要定义函数指针不需要获取函数指针。

http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html

http://www.cnblogs.com/madfrog/archive/2010/06/25/1765243.html

原创粉丝点击