现在我才知道opengl从3.0开始,所有实现全部由显卡厂商提供。而官方组织只是发布标准而已,由于没有这点儿认知,害的我到处找dll。GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口。使用OpenGL的朋友都知道,window目前只支持OpenGL1.1的涵数,但OpenGL现在都发展到2.0以上了,要使用这些OpenGL的高级特性,就必须下载最新的扩展,另外,不同的显卡公司,也会发布一些只有自家显卡才支持的扩展函数,你要想用这数涵数,不得不去寻找最新的glext.h,有了GLEW扩展库,你就再也不用为找不到函数的接口而烦恼,因为GLEW能自动识别你的平台所支持的全部OpenGL高级扩展涵数。也就是说,只要包含一个glew.h头文件,你就能使用gl,glu,glext,wgl,glx的全部函数。GLEW支持目前流行的各种操作系统(including Windows, Linux, Mac OS X, FreeBSD, Irix, and Solaris)。
(1)寻找缺失的 OpenGL 函数
OpenGL 是由显卡直接支持并实现的,当时在设计的时候考虑到显卡厂商可能会比操作系统 / 开发软件制造商先行一步提供新的扩展,所以有提供获取新的扩展的方法,在 Windows 下就是利用 wglGetProcAddress 函数:
PROC wglGetProcAddress(
LPCSTR lpszProc // name of the extension function
);
此函数与 GetProcAddress 功能类似,实现也类似,无非就是从动态库中通过名字直接获取到函数的地址。
FARPROC WINAPI GetProcAddress(
__in HMODULE hModule ,
__in LPCSTR lpProcName
);
因为 wglGetProcAddress 很明确的知道该从哪个 Dll 获取函数,所以省略了第一参数模块名,仅仅通过函数名就能获取到对应的函数地址,使用方法也是类似,通过函数名获取到函数地址后,通过强制转换的方式使用。此方法虽然可行,但是用到大量函数的时候比较麻烦。事实上,此方法提供的时候是作为一种补充的手段,是在显卡生厂商走在操作系统和开发工具提供商前面时的一种暂时应付手段,但是,很不幸的是, Windows 是在落后太多了。MS 当年作为 OpenGL 的发起人之一,仅仅对 OpenGL 支持到 1.1 ,然后就退出了 OpenGL 组织,自己发展 DirectX 系统去了,我们要在 Windows 上使用 OpenGL 光靠 MS 的话,那么 OpenGL 1.1 后的所有函数都得通过上述手段来完成,那简直是让人吐血的事情 -_-! Glew实际上为我们做了上述的所有事情!配置好Glew后以后在使用 OpenGL 的时候,都请通过下述代码找到OpenGL1.1 以上的函数。
#include <GL/glew.h> //包含必要的头文件
#include <GL/wglew.h>
#pragma comment ( lib , "glew32.lib" ) //链接时加入库文件
#pragma comment ( lib , "glew32s.lib" )
然后,在初始化 OpenGL 的时候,不要忘了将 glew 初始化,可以这样:
GLenum err = glewInit ();
if (err != GLEW_OK )
{
exit (-2);
}
这样就能使用缺失的函数,就像它们原来就被操作系统支持那样,而不用自己通过 wglGetProcAddress 去获取了,说是能像原来就被操作系统支持的那样使用其实不完成正确,起码在 VS 中,由于都是通过强转后的函数指针使用, VS 和 VA 都不能正确的解析其函数原型,使得代码编写时智能提醒函数原型的功能不能正常使用,这也算是个小瑕疵吧。
(2)Glew的安装和使用
推荐将头文件放在 Visual studio 的 include/GL 目录下(可以通过找到 gl/gl.h 的位置找到), lib 放在Visual studio 的 lib 目录下,动态库放到 windows/system32 这个系统目录下,那么以后的 OpenGL 工程就不需要额外的配置了。当然也可以通过“附加包含路径”指定包含头文件的目录和“附加库路径”来指定包含库文件的目录。包含了 glut 后,基本上 Win32 下 OpenGL 的工程可以以下面的代码开始了:
#include <GL/glew.h>
#include <GL/wglew.h>
#include <GL/glut.h>
#pragma comment ( lib , "opengl32.lib" )
#pragma comment ( lib , "glu32.lib" )
#pragma comment ( lib , "glew32.lib" )
#pragma comment ( lib , "glew32s.lib" )
#pragma comment ( lib , "glut32.lib" )
这些都是必须的。(事实上由于glut32.lib会自动的包含OpenGL核心所需的库,包含glut32.lib时可以省略opengl32.lib和glu32.lib)
下面是一个完整的实例,其中的宏 GL_VERSION_1_3 是由 glew 定义用来表示支持 OpenGL1.3 版本,其中的函数 glMultiDrawElementsEXT 就是 Windows 本身不支持,用了 glew 后才能使用的 OpenGL 扩展接口(首先要显卡支持啊)。
#include <GL/glew.h>
#include <GL/wglew.h>
#include <GL/glut.h>
#include <stdio.h>
#pragma comment ( lib , "opengl32.lib" )
#pragma comment ( lib , "glu32.lib" )
#pragma comment ( lib , "glew32.lib" )
#pragma comment ( lib , "glew32s.lib" )
#pragma comment ( lib , "glut32.lib" )
#ifdef GL_VERSION_1_3
void setupPointer (void ){
static GLint vertices [] = {25, 25,
75, 75,
100, 125,
150, 75,
200, 175,
250, 150,
300, 125,
100, 200,
150, 250,
200, 225,
250, 300,
300, 250};
glEnableClientState (GL_VERTEX_ARRAY );
glVertexPointer (2, GL_INT , 0, vertices );
}
void init (void ){
GLenum err = glewInit ();
if (err != GLEW_OK )
{
exit (-2);
}
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_SMOOTH );
setupPointer ();
}
void display (void )
{
static GLubyte oneIndices [] = {0, 1, 2, 3, 4, 5, 6};
static const GLubyte twoIndices [] = {1, 7, 8, 9, 10, 11};
static GLsizei count [] = {7, 6};
static const GLvoid * indices [2] = {oneIndices , twoIndices };
glClear (GL_COLOR_BUFFER_BIT );
glColor3f (1.0, 1.0, 1.0);
glMultiDrawElementsEXT (GL_LINE_STRIP , count , GL_UNSIGNED_BYTE ,
indices , 2);
// 上面的一句相当于下面的两句
//glDrawElements(GL_LINE_STRIP, count[0], GL_UNSIGNED_BYTE, oneIndices);
//glDrawElements(GL_LINE_STRIP, count[1], GL_UNSIGNED_BYTE, twoIndices);
glFlush ();
}
void reshape (int w , int h )
{
glViewport (0, 0, (GLsizei ) w , (GLsizei ) h );
glMatrixMode (GL_PROJECTION );
glLoadIdentity ();
gluOrtho2D (0.0, (GLdouble ) w , 0.0, (GLdouble ) h );
}
void keyboard (unsigned char key , int x , int y )
{
switch (key ) {
case 27:
exit (0);
break ;
}
}
int main (int argc , char ** argv )
{
glutInit (&argc , argv );
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize (350, 350);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv [0]);
init ();
glutDisplayFunc (display );
gutReshapeFunc (reshape );
glutKeyboardFunc (keyboard );
glutMainLoop ();
return 0;
}
#else
int main(int argc, char** argv)
{
fprintf (stderr, "This program demonstrates a feature which is not in OpenGL Version 1.0.\n");
fprintf (stderr, "If your implementation of OpenGL Version 1.0 has the right extensions,\n");
fprintf (stderr, "you may be able to modify this program to make it run.\n");
return 0;
}
#endif