精华内容
下载资源
问答
  • OPENGL命令

    2012-05-11 22:27:12
    很好的OPENGL指令,适合用在G4软件
  • opengl 版本检测

    2017-09-21 17:38:08
    OpenGL version supported by this platform: 1.0 supported: (null) 1.1 supported: (null) 1.2 supported: (null) 1.3 supported: (null) 1.4 supported: (null) 1.5 supported: (null) 2.0 supported: ...
  • opengl版本

    千次阅读 2013-01-15 21:44:06
     在Windows平台上没有这么简单。微软为了维护Direct3D,对OpenGL的支持很消极,其OpenGL实现仍然是1.1。由于Windows上的OpenGL程序最终都会动态链接到微软的OpenGL32.dll,可OpenGL32.dll只支持OpenGL 1.1,使我

    摘自:http://blog.csdn.net/kongbu0622/article/category/343937   

     在Windows平台上没有这么简单。微软为了维护Direct3D,对OpenGL的支持很消极,其OpenGL实现仍然是1.1。由于Windows上的OpenGL程序最终都会动态链接到微软的OpenGL32.dll,可OpenGL32.dll只支持OpenGL 1.1,使我们不能直接使用新版OpenGL,仍然要用扩展访问OpenGL1.1以来新增的功能。

      OpenGL Hardware Registry:由Delphi3D.net维护,列出了目前几乎所有3D加速卡的OpenGL硬件信息,包括其支持的扩展。当然,这里面列的扩展不能作为程序的依据,

    程序中要使用某个扩展,还是要先检查显卡是否支持。因为同样的显卡,如果驱动程序不同,支持的扩展也不相同,往往新的驱动程序会加入新的扩展,丢掉一些废弃的扩展。



     由于Windows上的OpenGL程序最终都会动态链接到微软的OpenGL32.dll,可OpenGL32.dll只支持OpenGL 1.1,使我们不能直接使用新版OpenGL,仍然要用扩展访问OpenGL1.1以来新增的功能。

         Windows怎么实现OpenGL硬件加速呢?OpenGL32.dll是微软的OpenGL 1.1纯软件实现,我们的程序都要动态链接到这个dll。如果安装3D芯片厂商的驱动程序,会将一个不同名字的dll放到Windows系统目录下,比如在Windows 2000下安装nVIDIA GeForce2 MX的驱动程序,会在系统目录下放一个nvoglnt.dll(这就是nVIDIA的OpenGL驱动),并在注册表中登记nvoglnt.dll,让Windows知道硬件加速OpenGL驱动的名字,以后运行OpenGL程序,OpenGL32.dll就会把OpenGL调用直接转到nvoglnt.dll。

     

    一: gl 的扩展:

    推荐使用下面2个扩展库:

    1. 使用glew

    glew是一个扩展库,包含了OpenGL中许多核心及扩展函数,现在的版本是1.4.0,支持OpenGL2.1,可以到这里下载:
    2. 使用glee
    glee也是一个扩展库,包含了OpenGL中许多核心及扩展函数,现在的版本是5.21,支持OpenGL2.1,可以到这里下载:
    二: glu的扩展:
    更新 glu.h 和 glu32.dll , 就可以了, 目前最新的版本是1.3, http://www.opengl.org/wiki/index.php/Getting_started
    http://www.geocities.com/vmelkon/glu.html
    三: 测试显卡对OpenGL的版本支持和扩展命令:

    可以装个这个软件Opengl Extensions Viewer , 可以测试显卡对OpenGL的版本支持和扩展命令。

     

     

    2.5 OpenGL扩展资料

    All About OpenGL Extensions:必读。

    讨论OpenGL扩展机制,讲述了如何阅读扩展官方说明书,并举了一些扩展的例子。

    OpenGL Extension Registry

    由SGI维护,列出了目前公开的所有扩展及其官方说明书。

    OpenGL Hardware Registry 由Delphi3D.net维护,列出了目前几乎所有3D加速卡的OpenGL硬件信息,包括其支持的扩展。当然,这里面列的扩展不能作为程序的依据,程序中要使用某个扩展,还是要先检查显卡是否支持。因为同样的显卡,如果驱动程序不同,支持的扩展也不相同,往往新的驱动程序会加入新的扩展,丢掉一些废弃的扩展。

     

     

     

     

     

     

     

     

     

     

     

     

     

    OpenGL入门学习(十四)(转)

    Windows系统如果没有安装显卡驱动,或者显卡驱动中没有附带OpenGL,则Windows系统默认提供一个软件实现的OpenGL,它没有使用硬件加速,因此速度可能较慢,版本也很低,仅支持1.1版本

    nVidiaATI这样的显卡巨头,其主流显卡基本上都提供了对OpenGL 2.1的支持。但一些旧型号的显卡因为性能不足等原因,只能支持到OpenGL 2.0或者OpenGL 1.5Intel的集成显卡,很多都只提供了OpenGL 1.4(据说目前也有更高版本的了,但是我没有见到)。

    OpenGL 2.0是一次比较大的改动,也因此升级了主版本号。可以认为OpenGL 2.0版本是一个分水岭,是否支持OpenGL 2.0版本,直接关系到运行OpenGL程序时的效果。如果要类比一下的话,我觉得OpenGL 1.5OpenGL 2.0的差距,就像是DirectX 8.1DirectX 9.0c的差距了。

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

    constchar* 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,怎么办呢?有一个被称为MESA的开源项目,用C语言编写了一个OpenGL实现,最新的mesa 7.0已经实现了OpenGL 2.1标准中所规定的各种功能。下载MESA的代码,然后编译,就可以得到一个最新版本的OpenGL了。呵呵,不要高兴的太早。MESA是软件实现的,就是说没有用到硬件加速,因此运行起来会较慢,尤其是使用新版本的OpenGL所规定的一些高级特性时,慢得几乎无法忍受。MESA不能让你用旧的显卡玩新的游戏(很可能慢得没法玩),但是如果你只是想学习或尝试一下新版本OpenGL的各种功能,MESA可以满足你的一部分要求。

    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则表示这是一个针对WindowsOpenGL扩展,如果是GLX则表示这是一个针对linuxX 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扩展。

    在程序中,判断OpenGL是否支持某个扩展
    前面已经说过,glGetString(GL_EXTENSIONS)会返回当前OpenGL所支持的所有扩展的名字,中间用空格分开,这就是我们判断是否支持某个扩展的依据。

    #include <string.h>
    //
    判断OpenGL是否支持某个指定的扩展
    // 若支持,返回1。否则返回0
    int hasExtension(constchar* name) {
    const char* extensions = (constchar*)glGetString(GL_EXTENSIONS);
    const char* end = extensions +strlen(extensions);
    size_t name_length = strlen(name);
    while( extensions < end ) {
    size_t position = strchr(extensions, ' ') - extensions;
    if( position == name_length &&
    strncmp(extensions, name, position) == 0 )
    return 1;
    extensions += (position + 1);
    }
    return 0;
    }



    上面这段代码,判断了OpenGL是否支持指定的扩展,可以看到,判断时完全是靠字符串处理来实现的。循环检测,找到第一个空格,然后比较空格之前的字符串是否与指定的名字一致。若一致,说明扩展是被支持的;否则,继续比较。若所有内容都比较完,则说明扩展不被支持。

    编写程序调用扩展的功能
    扩展的函数、常量,在命名时与通常的OpenGL函数、常量有少许区别。那就是扩展的函数、常量将以厂商的名字作为后缀。
    比如ARB扩展,所有ARB扩展的函数,函数名都以ARB结尾,常量名都以_ARB结尾。例如:
    glGenBufferARB(函数)
    GL_ARRAY_BUFFER_ARB(常量)
    如果已经知道OpenGL支持某个扩展,则如何调用扩展中的函数?大致的思路就是利用函数指针。但是不幸的是,在不同的操作系统中,取得这些函数指针的方法各不相同。为了能够在各个操作系统中都能顺利的使用扩展,我向大家介绍一个小巧的工具:GLEE
    GLEE是一个开放源代码的项目,可以从网络上搜索并下载。其代码由两个文件组成,一个是GLee.c,一个是GLee.h。把两个文件都放到自己的源代码一起编译,运行的时候,GLee可以自动的判断所有扩展是否被支持,如果支持,GLEE会自动读取对应的函数,供我们调用。
    我们自己编写代码时,需要首先包含GLee.h,然后才包含GL/glut.h(注意顺序不能调换),然后就可以方便的使用各种扩展功能了。

    #include"GLee.h"
    #include <GL/glut.h> //
    注意顺序,GLee.h要在glut.h之前使用



    GLEE也可以帮助我们判断OpenGL是否支持某个扩展,因此有了GLEE,前面那个判断是否支持扩展的函数就不太必要了。

    示例代码
    让我们用一段示例代码结束本课。
    我们选择一个目前绝大多数显卡都支持的扩展GL_ARB_window_pos,来说明如何使用GLEE来调用OpenGL扩展功能。通常我们在绘制像素时,需要用glRasterPos*函数来指定绘制的位置。但是,glRasterPos*函数使用的不是屏幕坐标,例如指定(0, 0)不一定是左下角,这个坐标需要经过各种变换(参见第五课,变换),最后才得到屏幕上的窗口位置。
    通过GL_ARB_window_pos扩展,我们可以直接用屏幕上的坐标来指定绘制的位置,不再需要经过变换,这样在很多场合会显得简单。

    #include"GLee.h"
    #include <GL/glut.h>

    void display(void) {
    glClear(GL_COLOR_BUFFER_BIT);

    if( GLEE_ARB_window_pos ) { //
    如果支持GL_ARB_window_pos
    //
    则使用glWindowPos2iARB函数,指定绘制位置
    printf("支持GL_ARB_window_pos\n");
    printf("
    使用glWindowPos函数\n");
    glWindowPos2iARB(100, 100);
    } else { //
    如果不支持GL_ARB_window_pos
    //
    则只能使用glRasterPos*系列函数
    // 先计算出一个经过变换后能够得到
    // (100, 100)的坐标(x, y, z)
    //
    然后调用glRasterPos3d(x, y, z);
    GLint viewport[4];
    GLdouble modelview[16], projection[16];
    GLdouble x, y, z;

    printf("
    不支持GL_ARB_window_pos\n");
    printf("
    使用glRasterPos函数\n");

    glGetIntegerv(GL_VIEWPORT, viewport);
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    gluUnProject(100, 100, 0.5, modelview, projection, viewport,
    &x, &y, &z);
    glRasterPos3d(x, y, z);
    }

    { //
    绘制一个5*5的像素块
    GLubyte pixels[5][5][4];
    //
    把像素中的所有像素都设置为红色
    int i, j;
    for(i=0; i<5; ++i)
    for(j=0; j<5; ++j) {
    pixels[i][j][0] = 255; // red
    pixels[i][j][1] = 0; // green
    pixels[i][j][2] = 0; // blue
    pixels[i][j][3] = 255; // alpha
    }
    glDrawPixels(5, 5, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    }

    glutSwapBuffers();
    }

    int main(int argc,char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(512, 512);
    glutCreateWindow("OpenGL");
    glutDisplayFunc(&display);
    glutMainLoop();
    }



    可以看到,使用了扩展以后,代码会简单得多了。不支持GL_ARB_window_pos扩展时必须使用较多的代码才能实现的功能,使用GL_ARB_window_pos扩展后即可简单的解决。
    如果把代码修改一下,不使用扩展而直接使用else里面的代码,可以发现运行效果是一样的。

    工具软件
    在课程的最后我还向大家介绍一个免费的工具软件,这就是OpenGL Extension Viewer(各大软件网站均有下载,请自己搜索之),目前较新的版本是3.0
    这个软件可以查看自己计算机系统的OpenGL信息。包括OpenGL版本、提供厂商、设备名称、所支持的扩展等。
    软件可以查看的信息很详细,比如查看允许的最大纹理大小、最大光源数目等。
    在查看扩展时,可以在最下面一栏输入扩展的名字,按下回车后即可连接到OpenGL官方网站,查找关于这个扩展的详细文档,非常不错。
    可以根据电脑的配置情况,自动连接到对应的官方网站,方便下载最新驱动。(比如我是nVidia的显卡,则连接到nVidia的驱动下载页面)
    可以进行OpenGL测试,看看运行起来性能如何。
    可以给出总体报告,如果一些比较重要的功能不被支持,则会用粗体字标明。
    软件还带有一个数据库,可以查询各厂商、各型号的显卡对OpenGL各种扩展的支持情况。

    小结

    本课介绍了OpenGL版本和OpenGL扩展。
    OpenGL从诞生到现在,经历了1.0, 1.1, 1.2, 1.2.1, 1.3, 1.4, 1.5, 2.0, 2.1这些版本。
    每个系统中的OpenGL版本可能不同。使用glGetString(GL_VERSION);可以查看当前的OpenGL版本。
    新版本的OpenGL将兼容旧版本的OpenGL,同时提供更多的新特性和新功能。
    OpenGL在实现时可以通过扩展,来提供额外的功能。
    OpenGL扩展有厂家扩展、EXT扩展、ARB扩展。通常应该尽量使用标准功能,其次才是ARB扩展、EXT扩展、厂家扩展。
    GLEE是一个可以免费使用的工具,使用它可以方便的判断当前的OpenGL是否支持某扩展,也可以方便的调用扩展。
    OpenGL Extension Viewer是一个软件,可以检查系统所支持OpenGL的版本、支持的扩展、以及很多的详细信息。

    ===================== 第十四课完 =====================
    =====================TO BE CONTINUED=====================

    展开全文
  • 1 opengl版本区别(在opengl官方文档中有详细说明)  针对Opengl不同版本的升级是主要是扩展指令集。  现在版本是4.0啦 1.1 opengl1.1 1995年,SGI推出了更为完善的OpenGL 1.1版本OpenGL 1.1的性能比1.0版提高...

    Windows7+VS2010下OpenGL的环境配置

    http://johnhany.net/2014/01/environment-for-opengl-with-vs2010/


    1 opengl的版本区别(在opengl官方文档中有详细说明)

        针对Opengl不同版本的升级是主要是扩展指令集。
        现在版本是4.0啦
    1.1 opengl1.1
    1995年,SGI推出了更为完善的OpenGL 1.1版本。OpenGL 1.1的性能比1.0版提高甚多。其中包括改进打印机支持,在增强元文件中包含OpenGL的调用,顶点数组的新特性,提高顶点位置、法线、颜色、色彩指数、纹理坐标、多边形边缘标识的传输速度,引入了新的纹理特性等等。
    1.2 opengl1.3
    2001年8月,ARB发布OpenGL 1.3规范,它增加了立方纹理贴图、纹理环境、多重采样、纹理框架压缩等扩展指令,但是改进程度非常有限。 
    1.3 opengl1.4
    2002年7月,ARB正式发布OpenGL 1.4,它也只加入了深度纹理/阴影纹理、顶点设计框架、自动纹理贴图等简单的功能。 
    1.3 opengl1.5
    2003年的7月,ARB公布OpenGL 1.5规范。OpenGL 1.5内包含ARB制定的“正式扩展规格绘制语言”(OpenGL Shading Language v1.0),该语言用于着色对象、顶点着色、片断着色等扩展功能,同时也将作为下一代OpenGL 2.0版本的内核。OpenGL 1.5的变化还增加了顶点缓冲对象(可提高透视性能)、非乘方纹理(可提高纹理内存的使用效率)以及阴影功能、隐蔽查询功能等等。其主要内容包括
    l         顶点Buffer Object:进行顶点配列方式可以提高透视性能
    l         Shadow功能:增加用来比较Shadow映射的函数
    l         隐蔽查询(QUERY):为提高Curling性能采用非同步隐蔽测试
    l         非乘方纹理(Texture):提高mipmap等纹理内存的使用效率
    l         OpenGL Shading Language v.1.0:用于着色(shader)对象、顶点着色以及片断着色技术(fragment shader )的扩展功能 
    1.4 opengl2.0
    OpenGL 1.0推出后的相当长的一段时间里,OpenGL唯一做的只是增加了一些扩展指令集,这些扩展指令是一些绘图功能,像是ClearCoat、Multisample、视频及绘图的整合工具(某些是通过OpenML的努力而开发出来的,它本身属于OpenGL ARB扩展指令之一。
    已经推出opengl2.0。OpenGL 2.0将在OpenGL 1.3基础上进行修改扩充、但它将有下面五个方面的重大改进:①复杂的核心被彻底精简;②完全的硬件可编程能力;③改进的内存管理机制、支持高级像素处理;④扩展至数字媒体领域,使之跨越高端图形和多媒体范畴;⑤支持嵌入式图形应用。
    为了在获得强大功能的同时保持理想的兼容性,OpenGL 2.0经历以下两个发展阶段:第一个阶段注重兼容能力和平滑过渡,为此,OpenGL 2.0核心将在精简后的OpenGL 1.3功能模块的基础上加上可完全兼容的新功能共同组成,这种做法在满足兼容性的同时,还可将原有OpenGL中数量众多、且相互纠缠不清的扩展指令进行彻底精简。 第一阶段的任务只是为了过渡,而第二阶段才是OpenGL 2.0的真正成熟期。此时,ARB将合成出一个“纯OpenGL 2.0”内核,纯内核将包含更多新增加的“精简型API函数”,这些函数具有完全的可编程特性、结构简单高效、功能强大且应用灵活。除了完成这项任务外,ARB组织还得指导开发商抛弃繁琐的OpenGL 1.X、转用更具弹性的“纯OpenGL 2.0”。 
    2 OpenGL扩展(OpenGL Extensions)
    OpenGL和Direct3D比较起来,最大的一个长处就是其扩展机制。硬件厂商开发出一个新功能,可以针对新功能开发OpenGL扩展,软件开发人员通过这个扩展就可以使用新的硬件功能。所以虽然显卡的发展速度比OpenGL版本更新速度快得多,但程序员仍然可以通过OpenGL使用最新的硬件功能。而Direct3D则没有扩展机制,硬件的新功能要等到微软发布新版DirectX后才可能支持。
        OpenGL扩展也不是没有缺点,正因为各个硬件厂商都可以开发自己的扩展,所以扩展的数目比较大,而且有点混乱,有些扩展实现的相同的功能,可因为是不同厂商开发的,接口却不一样,所以程序中为了实现这个功能,往往要为不同的显卡写不同的程序。这个问题在OpenGL 2.0出来后可能会得到解决,OpenGL 2.0的一个目标就是统一扩展,减少扩展数目。 
    2.1 扩展名
    每个扩展都有一个扩展名,扩展名类似如下形式:
                           GL_ARB_multitexture
    第一段GL,用来表示针对OpenGL哪部分开发的扩展,有以下几个值:
    GL  – 针对OpenGL核心的扩展
    WGL – 针对Windows平台的扩展
    GLX – 针对Unix / Linux平台的扩展
    GLU – 针对OpenGL Utility Library的扩展
    第二段ARB,用来表示是谁开发的这个扩展,常见以下几个值:
    ARB – 经OpenGL Architecture Review Board(OpenGL管理机构)正式核准的扩展,往往由厂商开发的扩展发展而来,如果同时存在厂商开发的扩展和ARB扩展,应该优先使用ARB扩展 
    EXT – 被多个硬件厂商支持的扩展
    NV  – nVIDIA 公司开发的扩展
    ATI – ATI公司开发的扩展
    ATIX– ATI公司开发的实验性扩展
    SGI – Silicon Graphics(SGI)公司开发的扩展
    SGIX– Silicon Graphics(SGI)公司开发的实验性扩展
    第三段multitexture就是真正的扩展名了,如multitexture就是多重纹理扩展。 
    2.2使用OpenGL扩展
         要使用一个OpenGL扩展,首先必须检查显卡是否支持这个扩展,以下代码可以获取一个显卡支持的的OpenGL扩展:
    const char *str = glGetString( GL_EXTENSIONS );
    函数返回一个字符串指针,这个字符串就是显卡所支持的所有扩展的扩展名,不同的扩展名之间用空格隔开,形如: 
    "GL_ARB_imaging GL_ARB_multitexture GL_ARB_point_parameters ……"    
        OpenGL扩展往往都会新增一些函数,在Windows平台上,这些函数不是通过.lib库连接到程序里的,而要在运行时动态获得函数的指针。我们以GL_ARB_point_parameters扩展为例看看怎么获得函数指针。  
    首先要定义函数指针类型,
    typedef void (APIENTRY * PFNGLPOINTPARAMETERFARBPROC)(GLenum pname,
    GLfloat param);
    typedef void (APIENTRY * PFNGLPOINTPARAMETERFVARBPROC)(GLenum pname,
    const GLfloat *params);
    这个工作SGI已经为我们做好,它提供了一个头文件 glext.h ,里面有目前绝大多数扩展的常量和函数指针定义,下载下来放到编译器的include/GL文件夹下面,然后在程序里面加上:
      #include <GL/glext.h>
    就可以在程序中使用常量和函数指针类型了。  
    然后要定义函数指针:
       PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
    PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;  
    再检查显卡是否支持GL_ARB_point_parameters扩展,其中isExtensionSupported是自定义的一个函数,就是在glGetString( GL_EXTENSIONS )返回的字符串里查找是否存在指定的扩展名:
      int hasPointParams = isExtensionSupported("GL_ARB_point_parameters");  
    如果支持,就可以用wglGetProcAddress函数获取扩展函数的指针:
    if (hasPointParams) 
      {
    glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)\
    wglGetProcAddress( "glPointParameterfEXT" );
    glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC) \
    wglGetProcAddress( "glPointParameterfvEXT" );
    }
    最后就可以在程序里使用扩展函数:
      if (hasPointParams)
      {
    static GLfloat quadratic[3] = { 0.25, 0.0, 1/60.0 };
    glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, quadratic);
    glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB, 1.0);
    }
     另外,下面代码说明如何访问扩展函数:(资料来源于csdn知识库)
    调用wglGetProcAddress函数访问一个不在标准OpenGL库中的扩展函数。如果该扩展函数存在当前的执行(implementation)中,那么wglGetProcAddress返回一个用来访问该函数的函数指针。否则,wglGetProcAddress返回NULL.
    例如,要访问glAddSwapHintRectWIN扩展函数,如下调用wglGetProcAddress: 
    // Get a pointer to the extension function.
    typedef void (WINAPI *FNSWAPHINT)(GLint, GLint, GLsizei, GLsizei);
    fnSwapHint = (FNSWAPHINT)wglGetProcAddress("glAddSwapHintRectWIN"); 
    // Actual call to glAddSwapHintRectWIN.
    if (fnSwapHint != NULL)
    (*fnSwapHint)(0, 0, 100, 100); 
    2.3 WGL扩展
         glGetString( GL_EXTENSIONS )取得的扩展字符串中并不包括针对Windows平台的WGL扩展,WGL扩展串要通过WGL_ARB_extensions_string扩展来获得,以下代码演示了如何获得WGL扩展串:   
    定义WGL_ARB_extensions_string扩展新增函数wglGetExtensionsStringARB的函数指针类型,同样这个工作SGI已经为我们做好,只不过不在glext.h中,而在它提供的另外一个头文件 wglext.h 中:
      typedef const char *(APIENTRY * PFNWGLGETEXTENSIONSSTRINGARBPROC)(
          HDC hdc); 
    定义函数指针:
      PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; 
    检查是否支持WGL_ARB_extensions_string扩展,如果不支持,表示这个显卡不支持WGL扩展,如果支持,则得到wglGetExtensionsStringARB函数的指针,并调用它得到WGL扩展串:
      int hasWGLext = isExtensionSupported("WGL_ARB_extensions_string");
      if (hasWGLext)
      {
        wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) \
    wglGetProcAddress( "wglGetExtensionsStringARB" );
        const char *wglExt = wglGetExtensionsStringARB( hdc );
        ……  }   

    2.4 OpenGL版本
    一些常用的OpenGL扩展会在新版的OpenGL中加到OpenGL核心中去,成为OpenGL标准的一部分,可以简化程序开发,程序员使用这些功能时不必做繁琐的扩展初始化工作。比如多重纹理功能,在OpenGL1.2.1加入到OpenGL核心中,以前要使用多重纹理,要先检查是否支持GL_ARB_multitexture扩展,然后初始化glActiveTextureARB等函数,很麻烦,而OpenGL1.2后,则可以直接使用glActiveTexture函数。
       不过,这种简化只有Mac/Unix/Linux程序员才能享受到,在Windows平台上没有这么简单。微软为了维护Direct3D,对OpenGL的支持很消极,其OpenGL实现仍然是1.1。由于Windows上的OpenGL程序最终都会动态链接到微软的OpenGL32.dll,可OpenGL32.dll只支持OpenGL 1.1,使我们不能直接使用新版OpenGL,仍然要用扩展访问OpenGL1.1以来新增的功能。
    2.5 OpenGL扩展资料 
    All About OpenGL Extensions:必读。
    讨论OpenGL扩展机制,讲述了如何阅读扩展官方说明书,并举了一些扩展的例子。
      OpenGL Extension Registry:
        由SGI维护,列出了目前公开的所有扩展及其官方说明书。
      OpenGL Hardware Registry:      由Delphi3D.net维护,列出了目前几乎所有3D加速卡的OpenGL硬件信息,包括其支持的扩展。当然,这里面列的扩展不能作为程序的依据,程序中要使用某个扩展,还是要先检查显卡是否支持。因为同样的显卡,如果驱动程序不同,支持的扩展也不相同,往往新的驱动程序会加入新的扩展,丢掉一些废弃的扩展。  
    2.6 OpenGL硬件加速
      在Windows平台上,OpenGL驱动可能有三种模式:纯软件、MCD和ICD: 
    纯软件模式:微软提供一个OpenGL的软件实现,所有渲染操作均由CPU完成,速度很慢。如果安装系统时使用Windows自带的显卡驱动程序,那么OpenGL程序就会运行在软件模式下。而且由于微软有自己的Direct3D,所以对OpenGL的支持很消极,它的OpenGL纯软件实现只支持OpenGL1.1,而目前OpenGL的最新版本为1.4 
    MCD(Mini Client Driver):MCD是早期微软在Windows NT上支持OpenGL时,为了简化驱动开发时使用的一个模型。在这个模型中,OpenGL渲染管线的变换、光照部分仍然由软件实现,而光栅化部分则由硬件厂商实现,因此只要硬件支持,MCD可以硬件加速光栅化部分。MCD虽然可以简化驱动开发,但是功能限制太大,现在市面上的3D加速卡均支持硬件变换和光照,MCD却不能利用这一特性,看上去MCD已经没有存在的价值 
    ICD(Installable Client Driver):ICD是一个完整的OpenGL驱动模型,比MCD复杂得多。硬件厂商要实现完整的OpenGL渲染管线,如变换、光照、光栅化等,因此只要硬件支持,ICD可以硬件加速整个OpenGL渲染管线。我们通常说的OpenGL硬件加速就是指的通过ICD模型获得的硬件加速,而现在硬件厂商提供的OpenGL驱动程序也都是依照ICD模型开发的。主要硬件厂商的ICD已经可以支持OpenGL的最新版1.4  
        Windows怎么实现OpenGL硬件加速呢?OpenGL32.dll是微软的OpenGL 1.1纯软件实现,我们的程序都要动态链接到这个dll。如果安装3D芯片厂商的驱动程序,会将一个不同名字的dll放到Windows系统目录下,比如在Windows 2000下安装nVIDIA GeForce2 MX的驱动程序,会在系统目录下放一个nvoglnt.dll(这就是nVIDIA的OpenGL驱动),并在注册表中登记nvoglnt.dll,让Windows知道硬件加速OpenGL驱动的名字,以后运行OpenGL程序,OpenGL32.dll就会把OpenGL调用直接转到nvoglnt.dll。  
       Windows平台上,一个OpenGL程序是否使用硬件加速由三个因素决定,这三个因素缺一不可,否则程序都会运行于纯软件模式:
    是否有一块3D加速卡
    是否安装了显卡厂商提供的最新的驱动程序,Windows自带的显卡驱动程序并不会提供OpenGL硬件加速能力
    指定的像素格式是否被显卡硬件所支持
      判断一种像素格式是否被显卡硬件所支持,可以用函数DescribePixelFormat取得该像素格式的数据,然后看结构体PIXELFORMATDESCRIPTOR中的dwFlags的值,如果
    PFD_GENERIC_FORMAT被置1,并且PFD_GENERIC_ACCELERATED被置0,即
    (pfd.dwFlags & PFD_GENERIC_FORMAT) && 
    !(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
    表明该像素格式不被显卡硬件支持,使用该像素格式的OpenGL程序将使用纯软件模式渲染
    PFD_GENERIC_FORMAT被置1,并且PFD_GENERIC_ACCELERATED被置1,即
    (pfd.dwFlags & PFD_GENERIC_FORMAT) && 
    (pfd.dwFlags & PFD_GENERIC_ACCELERATED)
    表明该像素格式被显卡硬件支持,并且程序使用MCD模式渲染
    PFD_GENERIC_FORMAT被置0,并且PFD_GENERIC_ACCELERATED被置0,
    !(pfd.dwFlags & PFD_GENERIC_FORMAT) && 
    !(pfd.dwFlags & PFD_GENERIC_ACCELERATED)
    表明该像素格式被显卡硬件支持,并且程序使用ICD模式渲染 
    3 OpenGL Extension 
    这个软件可以自动测试显卡对OpenGL的版本支持和扩展命令。 
    相关参考文献:
    《Opengl扩展机制》 (用google能够搜到,有代码实现)
    Extensions to OpenGL (opengl网站对extension的简单介绍)

    OpenGL 开发环境配置   OpenGL 下有一些重用的辅助库,比如glut,glee,glew等等,在windows平台下需要自己安装,因为微软为了推广自己的DX,在windows下只支持openGL 1.1版本。你可以打开\Microsoft Visual Studio X.X\VC\include\gl\gl.h 
    或 \Microsoft  SDKs\Windows\v6.1\Include\gl\gl.h 文件,查看微软默认支持的openGL版本号是:/* Version */
    #define GL_VERSION_1_1                    1 现在openGL已经发展到3.0了,因此我们需要自己下载配置这些库,在这里我们来安装glut, glee, glew这三个库,以及一些OpenGL扩展支持。 
    glut : 提供对窗口的封装,这是跨平台窗口的,我们就不必自己去编写烦琐的窗口代码。glee : 方便用来判断当前系统是不是支持某项OpenGL特性,我们就不用自己去写烦琐的先取函数地址然后再判断的代码了。glew : 因为windows默认只支持OpenGL 1.1,你要想用更高版本的OpenGL,你就需要安装它,它能自动识别你的平台所支持的全部OpenGL高级扩展函数。
    1,安装 glut GLUT3.7下载地址:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip
    点击上面的链接下载最新的GLUT,最新的GLUT版本是3.7,解压,将 glut32.dll 和 glut.dll 拷贝到 c:\windows\system32 下面,将 glut32.lib 和 glut.lib 拷贝到 VC 安装目录下的 lib 目录下(如:\Microsoft Visual Studio 9.0\VC\lib\下),将 glut.h 拷贝到VC安装目录下的 \include\gl\ 目录下(如:\Microsoft Visual Studio 9.0\VC\include\gl\下)。在程序中我们只需要把 #include <GL/gl.h>
    #include <GL/glu.h> 用 
    #include <GL/glut.h> 替换就可以了。因为在头文件 glut.h 中已经包含这些头文件,并导入了必要的库: 
    #pragma comment (lib, "winmm.lib")     /* link with Windows MultiMedia lib */#pragma comment (lib, "opengl32.lib")  /* link with Microsoft OpenGL lib */
    #pragma comment (lib, "glu32.lib")     /* link with OpenGL Utility lib */#pragma comment (lib, "glut32.lib")    /* link with Win32 GLUT lib */ 
    2,安装 glew下载链接:
    https://sourceforge.net/project/downloading.php?group_id=67586&filename=glew-1.5.1-win32.zip 点击上面的链接下载最新的GLEW(支持OpenGL 3.0),解压,将 \bin\glew32.dll 拷贝到 c:\windows\system32 下面,将 \lib\glew32.lib 拷贝到VC安装目录下的 lib 目录下(如:\Microsoft Visual Studio 9.0\VC\lib\下),将 \include\glew.h 和 \include\wglew.h 拷贝到 VC 安装目录下的 \include\gl\ 目录下(如:\Microsoft Visual Studio 9.0\VC\include\gl\下)。在程序中我们只需要在包含gl,glu 或 glut.h 之前包含 glew.h就可以了(注意:一定要先包含 glew.h),在在代码中加上这么一句: 
    #pragma comment (lib, "glew32.lib")  示例: 
    #include <GL/glew.h>#include <GL/glut.h> 
    #progrma comment(lib, "glew32.lib") 在创建OpenGL渲染context之后,调用 glewInit(); 初始化glew就可以了。 
    3,安装 glee GLee 主页:http://elf-stone.com/glee.php
    下载链接:http://elf-stone.com/getfile.php?title=GLee 点击上面的链接下载最新的GLee,解压,将 GLee.lib 拷贝到 VC 安装目录下的 lib 目录下(如:\Microsoft Visual Studio 9.0\VC\lib\下),将 GLee.h 拷贝到VC安装目录下的 \include\gl\ 目录下(如:\Microsoft Visual Studio 9.0\VC\include\gl\下)。在应用程序中,我们就可以像如下来使用: 
    #include <GL/GLee.h>#progrma comment(lib, "GLee.lib") 
    if( GLEE_ARB_multitexture ) // is multitexture support available?{
          glMultiTexCoord2fARB(...);    // safe to use multitexture}
    else {
          // fallback} 

    4,安装一些扩展支持下载这三个文件 glext.hglxext.h, 和 wglext.h ,放置到 VC 安装目录下的 \include\gl\ 目录下(如:\Microsoft Visual Studio 9.0\VC\include\gl\下)。使用的时候直接包含它们就可以了。

    转载地址:点击打开链接

    展开全文
  • 显卡OpenGL版本查看测试工具GPU_Caps_Viewer_1.9.4.zip
  • 大家好,今天给大家介绍一下OpenGL ES的命令队列及glFinish/glFlush。 我们知道,我们调用的OpenGL ES方法,都是在CPU上调用的,这些调用最终会被转换成GPU驱动指令而在GPU上执行,而CPU和GPU因为是两个不同的处理器...

    大家好,今天给大家介绍一下OpenGL ES的命令队列及glFinish/glFlush

    我们知道,我们调用的OpenGL ES方法,都是在CPU上调用的,这些调用最终会被转换成GPU驱动指令而在GPU上执行,而CPUGPU因为是两个不同的处理器,它们之间自然是可以并行地执行各自的指令,OpenGL ES有一个命令队列用于暂存还未发送到GPU的命令,实际上我们调用的绝大多数OpenGL ES方法,只是往命令队列时插入命令而已,并不会在CPU等命令执行完,因此如果大家去测耗时,会发现OpenGL ES大多数方法,基本都不耗时,无论渲染的东西多么复杂。

    我画了一个图来表示:

    这里注意一个细节,这个命令队列并不是所有的线程都对应同一个,命令队列是和EGL Context对应的,而一个线程又只能同时绑定到一个EGL Context(关于EGL、GL线程、线程共享EGL Context,可以参见我的另一篇文章《OpenGL ES 高级进阶:EGL及GL线程》),因此,可以理解为命令队列是和绑定的EGL Context的线程对应的。

    有时我们又希望在CPU上等待OpenGL ES命令执行完成,例如我们有时希望做多线程优化,在两个共享EGL Context的线程中,在一个线程中渲染,在另一个线程中用渲染好的纹理做其它操作等,那么在这种情况下,我们是不能像在CPU上做同步那样的,来看一段伪代码:

    // thread0:
    fun run() {
        ...
        // 调用glDrawXXX()渲染到texture上
        lock.notify()
        ...
    }
    // thread1:
    fun run() {
        ...
        lock.wait()
        // 将texture拿去用
        ...
    }
    复制代码

    代码中,我们希望在thread0完成渲染后,在thread1中将它读到bitmap中,这样会读到什么结果?基于前面的讨论,可以知道这样读到的结果是不确定的,因为thread0执行glDrawXXX()之后,并不会等待GPU真正执行了渲染,所以thread1在使用texture时,它的内容是不确定的,有可能还没开始渲染,也有可能渲染到了一半,或者是已经渲染完了。要得到正确的结果,在OpenGL ES 2.0中我们可以使用glFinsh(),在OpenGL ES 3.0中可以使用fence,后面我会写文章介绍fence,现在我们使用glFinish(),它的作用是在CPU上等待当前线程对应的命令队列里的命令执行完成,加上glFinish()后,我们就一定能得到正确的结果:

    // thread0:
    fun run() {
        ...
        // 调用glDrawXXX()渲染到texture上
        glFinish()
        lock.notify()
        ...
    }
    // thread1:
    fun run() {
        ...
        lock.wait()
        // 将texture拿去用
        ...
    }
    复制代码

    我画了个图来直观的展示:

    由于glFinish()要在CPU上等待,因此会对性能造成一定的影响,如果thread0是一个主渲染线程,那就会对帧率产生影响,因此把等待放到比较次要的thread1中会比较好,但是我们把glFinish()放到thread1可以吗?来看下面这张图:

    前面提到过,命令队列是每个绑定了EGL Context的线程各自有各自的,glFinish()只会等待当前线程的命令队列中的命令执行完成,也就是等待thread1的命令队列中的命令执行完成,因此是没有我们期望的效果的,在OpenGL ES 2.0中,是没有办法做到在一个线程中等待另一个线程的OpenGL命令的,在OpenGL ES 3.0中可以用fence实现。

    前面说到绝大多数OpenGL ES方法是不会等待的,那么什么方法会等待呢?刚才的glFinish()就是一个,此外,还有将texture读取出来的方法glReadPixels()也会等待,另外还有eglSwapBuffers(),实际这2个方法会隐式调用glFinish()所以有时候我们常常发现,glReadPixels()会耗时,于是有些人会认为,把texture读出来的操作很耗时,实际上这个读操作并没有多耗时,耗时是在等待命令队列中的所有命令执行完成。

    大家可以试一下,在glReadPixels()前如果先调glFinish()把命令队列清空,再执行glReadPixels(),会发现glReadPixels()没有想像中的那么耗时。

    glReadPixels()为什么会隐式调用glFinish()?大家可以这样理解,因为glReadPixels()是要将texture读出来,如果不保证之前的渲染命令执行完,那么读出来的结果就是不确定的,而eglSwapBuffers()为什么也会隐式调用glFinish()?可以类似地这样理解,因为eglSwapBuffers()是将双buffer进行交换从而让正在接受渲染的back buffer能显示出来,如果不保证所有渲染命令执行完,是不是有可能显示出来是残缺不全的?

    说到这,顺便提一下OpenGL ES的耗时测量,由于OpenGL ES大多数方法只是往命令队列里插入命令而不等待执行完成,因此要测量一段OpenGL ES操作的代码真正的耗时,需要在前后加上glFinish()

    glFinish()
    val startTime = System.currentTimeMillis()
    // 一顿OpenGL ES操作
    glFinish()
    val duration = System.currentTimeMillis() - startTime
    复制代码

    在前面也加glFinish()是为了将之前的命令先执行完,不要干扰我们的测量。

    glFinish()类似的还有一个方法是glFlush(),它的作用是将命令队列中的命令全部刷到GPU,但并不等它执行完成,因此有一些操作希望它能快些执行,但又不是特别急切到马上等它执行完成,这时候就可以用glFlush()

    感谢阅读!

    转载于:https://juejin.im/post/5d047d5be51d4510aa0114f2

    展开全文
  • OpenGL命令

    千次阅读 2012-02-16 14:11:39
    许多O p e n G L命令直接影响诸如点、线、多边形以及位图等 O p e n G L对象的绘制。而另一些命令,例如那些用于反走样或纹理操作的命令,主要用来控制图像如何生成。还有一些命令则关注帧缓冲区的操作。 本章介绍...
     许多O p e n G L命令直接影响诸如点、线、多边形以及位图等  O p e n G L对象的绘制。而另一些命令,例如那些用于反走样或纹理操作的命令,主要用来控制图像如何生成。还有一些命令则关注帧缓冲区的操作。
    
    本章介绍所有  O p e n G L命令是如何协同工作来建立  O p e n G L处理流程的。同时也对O p e n G L实用库(G L U)和对X窗口系统的 O p e n G L扩展(G L X)中的命令作了概述。
    本章包括以下几个主要部分:
    • O p e n G L处理流程:在第1章的基础上讲解特定的 O p e n G L命令如何控制数据的处理。
    • 其他O p e n G L命令:讨论几个前一章中没有提及的 O p e n G L命令集。
    • O p e n G L实用库:介绍了已有的G L U例程。
    • 对X窗口系统 的O p e n G L扩展:介绍G L X中有用的例程。
    2.1   OpenGL处理流程
    第1章介绍了 O p e n G L如何工作,本章将进一步讨论各阶段中数据处理的实际情况并且将各阶段与其用到的命令结合起来。图 2 - 1是一幅较为详细的 O p e n G L处理流程图。
    从图中我们可以看到其中有三组箭头穿过了大多数的阶段。这三组箭头分别代表了顶点和与其相关的两个主要的数据类型—颜色值和纹理坐标。值得注意的是顶点首先组合成图元,然后是片断,最后成为帧缓冲区中的像素。这一过程将在下面章节中作详细介绍。
    一个O p e n G L命令的效果将很大程度地依赖于某特定模式是否有效。例如,与光照有关的命令只有当你启动了光照功能才能有效地生成一个适当的光照对象。如果要启动一个特定的模式,请调用glEnable( )命令,并且要提供一个适当的常量来确定该模式(如  G L _ L I G H T I N G)。下面章节中并没有介绍特定的模式,但在函数 g l E n a b l e ( )的使用说明中提供了一个完整的列表用来说明它可启动的模式。调用函数 g l D i s a b l e ( )可以关闭一个模式。
    2.1.1   顶点
    本节介绍与在图2 - 1中与各顶点操作有关的O p e n G L命令。它包含了有关顶点数组的各种信息。
    1. 输入数据
    你必须为O p e n G L流程提供几种输入数据类型。
    • 顶点—顶点用来描述所需要的几何对象的形状。你可以通过在函数对 g l B e g i n ( ) / g l E n d ( )之间调用函数 g l Ve rt e x * ( )来指定顶点,并用这些顶点建立点、线或多边形。你也可以用函数g l R e c t * ( )来直接绘制一个完整的矩形。
    • 边界标志 —在缺省情况下,多边形的所有边都是边界边。用函数 g l E d g e F l a g * ( )可以显式地设置边界标志。

    • 当前光栅位置 — 当前光栅位置用来确定绘制像素和位图时的光栅坐标。它由函数g l R a s t e r P o s * ( )指定。


    图2-1   OpenGL处理流程的各个阶段

    • 当前法线 —每个法向量都与一个特定的顶点相对应,它用来确定顶点处的表面在三维空间中的方向。它同时又影响该顶点所接收的光照的多少。函数   g l N o r m a l * ( )用来指定一个法向量。
    • 当前颜色—一个顶点的颜色用来确定光照对象最终的颜色。在  R G B A模式下,可以通过函数g l C o l o r * ( )来指定颜色;在颜色索引模式下则需使用函数 g l I n d e x * ( )。
    • 当前纹理坐标—纹理坐标用来确定在纹理映射表中的位置,此位置与一个对象的某个顶点相关联。它们可以由函数 g l Te x C o o r d * ( )指定。当系统支持 A R B多重纹理扩展时用函数g l M u l t i Te x C o o r d * A R B ( )。
    当调用函数 gl Ve rtex*( )时,生成的顶点将继承当前的边界标志、法线、颜色和纹理坐标。
    因此,必须在函数 g l Ve rtex*( ) 之前调用函数 g l E d g e F l a g * ( )、g l N o r m a l * ( )、g l C o l o r * ( )和g l TexCoord*( )来影响所生成的新顶点。
    上面所列的所有顶点的输入数据可以通过使用  “顶点数组”来指定,在下面的叙述中会有详细介绍。它允许通过调用单个函数来传送顶点数组数据。某些  O p e n G L机制可能用该方法来指定顶点会更有效。
    2. 矩阵转换
    顶点和法线首先要各自通过矩阵转换后才能用于在帧缓冲区中生成图像。顶点通过模式取景矩阵和投影矩阵转换,而发光的法线则由模式取景矩阵转换。你可以使用诸如      g l M a t r i x M o d e ( )、g l M u l t M a t r i x * ( )、g l R o t a t e * ( )、g l Tr a n s l a t e * ( )和g l S c a l e * ( )等函数来组成所需的转换。或者,也可直接用函数 g l L o a d M a t r i x * ( )和g l L o a d I d e n t i t y ( )指定矩阵。用函数 glPushMatrix()和g l P o p M a t r i x ( )可以在各自的堆栈中存储和恢复模式取景矩阵和投影矩阵。
    3. 光照和着色
    除了指定颜色和法向量外,你还可以用函数 g l L i g h t * ( )和g l L i g h t M o d e l * ( )指定所需的光照环境,用函数  g l M a t e r i a l * ( ) 指定所需的材料属性。用于控制光照计算的相关命令有:
    g l S h a d e M o d e l ( )、g l F ro n t F a c e ( )和g l C o l o r M a t e r i a l ( )。
    4. 生成纹理坐标
    O p e n G L并不明确地提供纹理坐标,而是用其他顶点数据的函数来生成它们。这项工作由函数g l TexGen*( )完成。当纹理坐标被指定或生成之后,它们将通过纹理矩阵实现转换。控制这些矩阵所使用的命令与前面“矩阵转换”一节中所提及的命令是一样的。
    5. 图元集
    一旦所有的计算执行完,这些顶点—连同各顶点相应的边界标志、颜色和纹理信息—将被组合成图元(包括点、线段和多边形)。
    6. 顶点数组
    你只需调用有限的几个命令就可以通过顶点数组来指定几何图元。当你调用函数g l D r a w A r r a y s ( )来绘制图元时,你不需要再通过调用一个个的 O p e n G L函数来传送每个单独的顶点、法线或颜色,而只要调用一个 g l D r a w A r r a y s ( )函数来分别指定顶点数组、法线数组和颜色数组就可以用它们来定义一系列要绘制图元(所有同一类型的)。函数 g l Ve rt e x P o i n t e r ( )、g l N o r m a l P o i n t e r ( )、 g l C o l o r P o i n t e r ( )、 g l I n d e x P o i n t e r ( ) 、g l Te x C o o r d P o i n t e r ( )和g l E d g e F l a g P o i n t e r ( )用来描述数组的组织结构和存储单元的位置。函数 g l E n a b l e C l i e n t S t a t e ( )和g l D i s a b l e C l i e n t S t a t e ( )用来指定将访问哪个顶点数组中的顶点坐标和属性。
    一个顶点的所有当前有效的数据都可以通过在函数对     g l B e g i n ( ) / g l E n d ( )之间调用函数g l A r r a y E l e m e n t ( )来指定。此外,函数 g l D r a w E l e m e n t s ( )和g l D r a w R a n g e E l e m e n t s ( )可以随机访问顶点数组。
    7. 图元
    在流程的下一个阶段中,图元将被转化成像素片断。该过程有以下几个步骤:适当地剪切图元;对颜色和纹理作必要的相关调整;将有关坐标转换成窗口坐标;最后,将剪切好的图元通过光栅化处理而转换成像素片断。
    8. 剪切
    当点、线段和多边形需要剪切时, O p e n G L对它们的处理稍有不同。对于点而言,要么维持其原始状态(当它包含在剪切体积内时),要么被丢弃(当它处于剪切体积外时)。对于线段和多边形则不尽相同。如果线段或多边形的一部分处于剪切体积外,则在剪切点的位置上生成一个新的顶点。而对于多边形,这些新的顶点之间还需要重新连一条完整的边。当线段和多边形被剪切时,其边界标志、颜色和纹理信息都被赋给新顶点。
    剪切实际上有两个步骤:
    1)  由 应 用 所 指 定 的 剪 切 。图元一旦被组合而成,它们将根据应用的要求,通过函数
    g l C l i p P l a n e ( )指定的剪切平面在眼坐标中进行剪切。(任何的 O p e n G L机制都支持至少六个这样的应用相关的剪切平面)。
    2)  视体剪切。接下来,图元将由投影矩阵转换(成剪切坐标)并被相应的视体剪切。你可以通过矩阵转换命令来控制这些矩阵。但更多地,它们由函数 g l F r u s t u m ( )和g l O r t h o ( )指定。
    9. 转换成窗口坐标
    在剪切坐标转换成窗口坐标 前,它们先要被归一化,即通过除以 w值从而生成归一化设备坐标。之后,通过视口转换将这些归一化的坐标变为窗口坐标。你可以用函数   g l D e p t h R a n g e ( )和g l Vi e w p o rt ( )来控制这些视口—它们将决定显示图像的窗口屏幕区域。
    10. 光栅化
    光栅化是将一个图元转化为一个二维图像的操作。该图像中的每个点都包含这样一些信息:
    颜色、深度和纹理数据。点及其相关信息被称为一个“片断”。
    当前光栅位置(由函数 g l R a s t e r P o s * ( )指定)在该阶段的像素绘制和位图中有多种用途。三种不同类型的图元的光栅化是各不相同的。另外,像素矩形和位图均需被光栅化。
    • 图元 。下面的命令允许你通过选择图元的尺寸及点画模式对图元的光栅化进行控制:
    g l P o i n t S i z e ( )、g l L i n e Wi d t h ( )、g l L i n e S t i p p l e ( )和g l P o l y g o n S t i p p l e ( )。你也可以通过命令g l C u l l F a c e ( )、g l F ro n t F a c e ( )和g l P o l y g o n M o d e ( )来控制正面多边形和背面多边形将如何被光栅化。
    • 像素。有几个命令用于控制像素的存储和传送模式。命令  g l P i x e l S t o re * ( )用来控制像素在客户端存储器中的编码方式, g l P i x e l Tr a n s f e r * ( )和g l P i x e l M a p * ( )控制像素存入帧缓冲区之前的处理方式。另外,当你使用的 O p e n G L机制支持“ A R B绘图子集”(参见 2 . 1 . 2节)时,就可以对像素进行其他处理。像素矩形由函数    g l D r a w P i x e l s ( )指定,其光栅化由函数
    g l P i x e l Z o o m ( )控制。
    • 位图。位图是由0和1所组成的矩形,它用来指定一个将要生成的特定格式的片断图案。每个这样的片断都有相同的相关数据。位图由函数 g l B i t m a p ( )指定。
    • 纹理。当纹理功能启动后,它将把一个指定的纹理图像的一部分映射到每个图元上。要想实现这种映射,你需要使用由片断的纹理坐标所确定的存储单元中的纹理图像的颜色来修改该片断的 R G B A颜色。
    你可你可以用函数 g l TexImage1D(), glTe x I m a g e 2 D ( )或g l Te x I m a g e 3 D ( )来指定一个纹理图像。如果要通过拷贝帧缓冲区中的数据来建立一个纹理图像,请使用函数     g l C o p y Te x I m a g e 1 D ( )或g l C o p y Te x I m a g e 2 D ( )。你也可以通过 g l TexSubImage1D(), glTe x S u bI m a g e 2 D ( )或  g l Te x I m a g e 3 D ( )载入子图像,或通过函数  g l C o p y Te x S u b I m a g e 1 D ( ) ,g l C o p y Te x S u b I m a g e 2 D ( )或g l C o p y S u b I m a g e 3 D ( )用从帧缓冲区中拷贝来的数据替换部分纹理图像。函数 g l Te x P a r a m e t e r * ( )和g l Te x E n v * ( )用来控制对纹理值进行解释并应用于一个片断。
    要指要指定具体哪些纹理优先存入纹理内存,需先调用函数  g l B i n d Te x t u re ( )生成指定的纹理 ( 纹 理 对 象 ),然后再调用函数    g l P r i o r i t i z e Te x t u re s ( ) 给它们排序。函数g l D e l e t e Te x t u re ( )可以删除一个纹理对象。
    • 颜色总和 。是指在纹理操作之后,将由镜面光照计算而来的颜色片断加到片段上。通过函数 g l L i g h t M o d e l ( ) 且将 G L _ L I G H T _ M O D E L _ C O L O R _ C O N T R O L 参数赋值为G L _ S E PA R AT E _ S P E C U L A R _ C O L O R可以指定镜面光照颜色进行分别计算。
    • 雾。O p e n G L可以将一种雾颜色和一种已光栅化的片断的纹理颜色用一个融合因子融合在一起。该融合因子由观察点与片断之间的距离决定。用函数g l F o g * ( )可指定雾颜色和融合因子。
    • 多边形偏移。当你绘制消隐图形或对表面进行贴面时,应该考虑使用函数g l P o l y g o n O ffset() 替换一个片断的深度值。该深度值是在绘制多边形时将一个特定的偏移量加到一个可调节的量上而生成的。该可调节量依赖于多边形深度值的变化量及它的屏幕尺寸。这种替换允许在同一个面上绘制多边形而相互间不产生影响。你可以启动如下所示的三种多边形模式之一来确定将采用怎样的替换方法。这三种多边形模式是      G L _ P O LY G O N _ O F F S E T _ F I L L ,G L _ P O LY G O N _ O F F S E T _ L I N E和G L _ P O LY G O N _ O F F S E T _ P O I N T。
    多边形偏移可用于绘制消隐图形、绘制高亮边的实心体及将贴面应用于物体表面。
    2.1.2   ARB绘图子集
    O p e n G L机制可以支持任选的 OpenGL ARB绘图子集。该集合是由数个附加的像素处理操作组成的。下面的功能仅当调用函数   g l L i g h t S t r i n g( GL_EXTENSIONS ) 的返回值是字符串G L _ A R B _ i m a g i n g时才有效。
    A R B图形子集所包含的功能如下所示:
    • 颜色表。颜色查询表提供了一种替换单个像素的方法。颜色表可用 g l C o l o r Ta b l e例程指定。如果要指定一个基于帧缓冲区值的颜色表,可以调用函数    g lCo p y C o l o r Table( ) 。函数g l C o p y S u b Ta b l e ( )允许你替换颜色表的一部分。而函数 g l C o p y C o l o r S u b Ta b l e ( )将使用帧缓冲区中的值替换指定的部分。在指定颜色表时可以对它进行缩放和偏移。用函数g l C o l o r Ta b l e P a r a m e t e r * ( )来指定缩放和偏移值。
    • 卷积滤波器。卷积是结合附近的像素来计算一个最终的像素值的方法。卷积滤波器可由函数g l C o n v o l u t i o n F i l t e r 1 D ( )、g l C o n v o l u t i o n F i l t e r 2 D ( )或g l S e p a r a b l e F i l t e r 2 D ( )指定。另外,卷积滤波器也可以用帧缓冲区中的值来指定,这时需要调用函数glCopyConvolutionFilter1D()  和g l C o p y C o n v o l u t i o n F i l t e r 2 D ( )。卷积滤波器可以通过函数g l C o n v o l u t i o n P a r a m e t e r * ( )指定的值对它进行缩放和偏移。经过卷积操作后,所得的像素值也可以进行缩放和偏移,函数
    glPixelTransfer*()用来指定缩放和偏移值。
    • 颜色矩阵转换 。矩阵转换可通过颜色矩阵堆栈而应用于像素。函数      g l M a t r i x M o d e(GL_COLOR )用来修正当前的颜色矩阵。有关内容请参阅“矩阵转换”。经过颜色矩阵转换之后,像素值可以通过函数 g l P i x e l Tr a n s f e r * ( )指定的值进行缩放和偏移。
    • 直方图。直方图用来确定像素矩形中值的分布情况。函数 g l H i s t o g r a m ( )用来指定哪些颜色组件将被计数。用函数  g l G e t H i s t o g r a m ( )可以返回直方图的计算结果。函数   g l R e s e t H i s t o g r a m ( )可以重新设置直方图表,而调用函数 g l G e t H i s t o g r a m P a r a m e t e r * ( )将返回用于描述直方图表的值。
    • 最值。每个像素矩形的最小和最大值可以用函数 g l M i n m a x ( )来计算。函数g l G e t M i n m a x ( )返回通过函数 g l M i n m a x ( )指定的颜色组件而计算所得的最小和最大值。调用函数   g l R e s e t M i n m a x ( )可以重新设置内部的最值表,而调用函数 g l G e t M i n m a x P a r a m e t e r * ( )将返回用于描述该表的参数值。
    • 融合方程。除了汇总外,像素还可以用融合而非叠加方式进行合并。函数g l B l e n d E q u a t i o n ( ) 用来指定源和目标像素值将如何被合并。
    • 常数融合颜色。除了标准融合函数外, A R B绘图子集允许用常数作为源或目标颜色值的系数。调用函数 g l B l e n d C o l o r ( )来指定常数融合颜色,它将与函数 g l B l e n d F u n c ( )所指定的融合系数一起使用。
    2.1.3   片断
    当一个通过光栅化而生成的片断能通过一系列的测试时,  O p e n G L允许通过该片断来修正帧缓冲区中相应的像素。如果该片断没通过测试,则该片断可被用来直接替换帧缓冲区中的值,或者与帧缓冲区中已存在的值合并。具体情况将视特定模式的状态而定。
    1. 像素所有权测试
    第一项测试用来检验与一个特定的片断相应的帧缓冲区中的像素是否属于当前的  O p e n G L环境。如果是,则对片断进行下一项测试;否则,将通过窗口系统来决定是丢弃该片断还是要对该片断进行后面的操作。当一个 O p e n G L窗口不明确时,这一测试允许窗口系统来控制  O p e n G L的行为。
    2. 裁剪测试
    裁剪测试将丢弃通过函数 g l S c i s s o r ( )指定的任意屏幕上的校正矩形区域外的片断。

    3. A l p h a测试
    A l p h a测试(它仅在 R G B A模式下执行)将根据片断的 a l p a h值和一个常数参考值之间的比较结果而丢弃一个片断。该比较命令和参考值由函数 g l A l p h a F u n c ( )指定。
    4. 模板测试
    模板测试将基于模板缓冲区中的值和一个参考值的比较结果而丢弃一个片断。函数g l S t e n c i l F u n c ( )用来指定所使用的比较命令及参考值。不管片断是否能通过模板测试,模板缓冲区中值的修正都由函数 g l S t e n c i l O p ( )决定。
    5. 深度缓冲测试
    当对一个片断进行的深度比较操作失败时,深度缓冲测试将丢弃该片断。函数     g l D e p t h F u n c ( )用来指定比较命令。当模板缓冲区有效时,深度比较的结果也将影响模板缓冲区的更新值。
    6. 融合
    融合是将一个片断的 R、G、B和A值与存放于帧缓冲区相应存储单元中的值合并。该操作仅在R G B A模式下才能使用。它根据片断的  a l p h a值与当前存储的像素相应值而产生不同的操作,它也受R G B值的限制。为了控制融合操作,你可以调用函数 g l B l e n d F u n c ( )来指定源和目标融合因子。
    当O p e n G L机制支持A R B绘图子集时,它将提供一些附加的融合功能,有关细节请参阅2 . 1 . 2节“A R B图形子集”。
    7. 抖动
    当抖动功能启动后,  O p e n G L将对片断的颜色或颜色索引应用一种抖动算法。该算法仅由片断的值及其 x和y窗口坐标决定。
    8. 逻辑操作
    逻辑操作可在片断和存储于帧缓冲区相应位置中的值之间使用。其结果将替换当前帧缓冲区中的值。你可以通过函数 glLogicOp( )来选择理想的逻辑操作。逻辑操作只能应用于颜色索引值,它不能用于R G B A值。
    9. 像素
    在O p e n G L流程的前一阶段中,片断被转换成了帧缓冲区中的像素。帧缓冲区实际上组成了一系列逻辑缓冲区,这些缓冲区包括:颜色缓冲区、深度缓冲区、模板缓冲区和累积缓冲区。
    其中颜色缓冲区由前左、前右、后左、后右以及一定数量的辅助缓冲区所构成。你可以用命令控制这些缓冲区,也可以直接从它们中读取或拷贝像素。(请注意:你所使用的特定的 O p e n G L环境不一定提供了所有这些缓冲区。)
    10. 帧缓冲区操作
    你可以用函数 g l D r a w B u ff e r ( )来选取你想写入颜色值的缓冲区。另外,当所有片断操作已执行完成以后,你还可以用四个不同的命令对每个逻辑帧缓冲区中位的写入进行屏蔽。这四个命令是g l I n d e x M a s k ( )、g l C o l o r M a s k ( )、g l D e p t h M a s k ( )和g l S t e n c i l M a s k ( )。累积缓冲区的操作由函数g l A c c u m ( )控制。此外,函数 g l C l e a r ( )可以将一个指定的缓冲区子集中的每个像素设置成某个指定值,该指定值由函数 g l C l e a r C o l o r ( )、g l C l e a r I n d e x ( )、g l C l e a r D e p t h ( )、g l C l e a r S t e n c i l ( )或g l C l e a r A c c u m ( )指定。
    11. 读取或复制像素
    你可以将由帧缓冲区中读出的像素读入内存中,也可以用各种方式将它们编码,并将编码结果存入内存中。函数 g l R e a d P i x e l s ( )可用来完成上述工作。另外,你可以用函数 g l C o p y P i x e l s ( )将帧缓冲区的某个区域中的一个像素矩形的值复制到另一个区域。函数  g l R e a d B u ff e r ( )用来控制从哪个颜色缓冲区中读取或复制像素。
    2.2   其他OpenGL命令
    本节主要介绍一组特殊的命令。这些命令在图 2 - 1中并没有被明确地作为 O p e n G L处理流程的一部分而显示出来。这些命令实现了诸如多项式求值、显示列表的使用以及获取  O p e n G L状态变量的值等多项任务。
    2.2.1   使用求值器
    O p e n G L的求值器命令允许你用一个有理多项式映射来生成顶点、法线、纹理坐标及颜色。这些计算所得的值将通过流程,就象它们是被直接指定的一样。该求值工具也被  N U R B S(N o n Uniform Rational B-Spline)命令所使用,该命令允许你定义曲线和曲面。具体情况请参阅 2 . 3节“O p e n G L实用库”及本书第6章。
    使用求值器前,你首先必须用函数 g l M a p * ( )定义适当的一维或二维多项式映射。你可以用下面两种方法之一来指定和求取该映射的域值:
    • 首先用函数g l M a p G r i d * ( )定义一系列用于映射的等间隔域值,然后用函数 g l E v a l M e s h * ( )求取该网格的一个矩形子集。如果要想求取网格中的一个单独的点,请你使用函数g l E v a l P o i n t * ( )。
    • 将一个期望的域值明确地指定为函数 g l E v a l C o o r d * ( )的自变量,这时将求取该域值的映射。
    2.2.2   执行选择和反馈
    选择、反馈和绘制是三种互斥的操作模式。在通过光栅化而生成片断的过程中,绘制是它的默认模式。在选择和反馈模式中,没有片断生成,因此也不对帧缓冲区进行修改。在选择模式中,你可以决定将把哪些图元绘入窗口的某个区域;而在反馈模式中,即将被光栅化的图元的信息被返回给应用程序。你可以通过函数 g l R e n d e r M o d e ( )来选取所需的模式。
    1. 选择
    选择操作是通过返回的名称堆栈的当前内容来工作的。名称堆栈是一个整型名称数组。你可以在模式代码中指定名称并建立名称堆栈。该模式代码的作用是指定将要绘制的对象的几何形状。
    一旦图元与剪切体积相交,将有一个选择命中产生。该命中纪录将被写入函数     g l S e l e c t B u ffer()  提供的选择矩阵中。命中纪录中包含有命中发生时名称堆栈的内容。(请注意:函数g l S e l e c t B u ff e r ( )必须在O p e n G L被函数g l R e n d e r M o d e ( )设置成选择模式之前调用。同时,在函数g l R e n d e r M o d e ( )将O p e n G L退出选择模式之前也不能保证名称堆栈中所包含的内容都被返回。)

    你可以使用函数 g l I n i t N a m e s ( )、g l L o a d N a m e ( )、g l P u s h N a m e ( )和g l P o p N a m e ( )来操作名称堆栈。对于选择模式我们可以考虑使用 O p e n G L实用库( G L U)中的例程g l u P i c k M a t r i x ( ),该例程在2 . 3节“O p e n G L实用库”及本书第 6章中将有详细介绍。
    2. 反馈
    在反馈模式中,每个光栅化的图元将生成一个数值块,并将其拷贝到反馈数组中。你可用函数g l F e e d b a c k B u ff e r ( )提供这个数组。而这一函数必须在 O p e n G L设置成反馈模式前被调用。每个数值块开始的一个代码用来指明图元的类型,接下来是描述图元的顶点和相关数据的值。它们也可以被写入位图和像素矩形。在调用函数 g l R e n d e r M o d e ( )使O p e n G L退出反馈模式之前,并不能保证已将数据写入了反馈数组。在反馈模式下,你可以使用函数 g l P a s s T h rough() 提供一个标记,它在反馈模式里被返回,就象它是个图元一样。
    2.2.3   显示列表的使用
    一个显示列表就是一组被存储起来以备以后执行的  O p e n G L命令。函数 glNewList( )用来创建一个显示列表,函数 glEndList( )结束创建工作。绝大多数在 g l N e w L i s t ( )和glEndList( )  之间被调用的 O p e n G L命令都被添加到显示列表并被选择执行。(函数glNewList( )的参考说明中列出了所有不能在显示表中存储并执行的命令。)如果要执行一个或一组显示表,你可调用函数glCallList( )或glCallLists( ),并同时提供用于识别一个或一组特定显示表的数字。你可以通过函数glGenLists( )、glListBase( )和glIsList( )来管理用于识别显示表的索引。函数 g l D e l e t e L i s t s ()用来删除一组显示表。
    2.2.4   模式和运行的管理
    许多 O p e n G L 命令的执行结果都跟某一特定的模式是否有效有关。你可以使用函数g l E n a b l e ( )和g l D i s a b l e ( )来设置这样的模式,也可以用函数 glIsEnabled( )来确认某一特定的模式是否已被设置。
    你可以使用函数 g l F i n i s h ( )来控制以前已发布的 O p e n G L命令的执行,该函数将强迫所有的命令完成。你也可以用函数 g l F l u s h ( ),它将确保所有这些命令在有限的时间内完成。
    O p e n G L的一个特殊实现是函数 g l H i n t ( )。你可以通过该函数使用“提示”来控制绘制的某些方面。你同样可以控制颜色和纹理坐标插入值的质量、雾化计算的精度以及反走样点、线或多边形的样本质量。
    2.2.5   获取状态信息
    O p e n G L含有大量的状态变量,它们对许多命令的行为都将产生影响。下列变量指定了特定的查询命令:
    g l G e t C l i p P l a n e
    g l G e t C o l o r Ta b l e †
    g l G e t C o l o r Ta b l e P a r a m e t e r †
    g l G e t C o n v o l u t i o n F i l t e r †
    g l G e t C o n v o l u t i o n P a r a m e t e r †
    g l G e t H i s t o g r a m †

    g l G e t H i s t o g r a m P a r a m e t e r †
    g l G e t L i g h t
    g l G e t M a p
    g l G e t M a t e r i a l
    g l G e t M i n m a x †
    glGetMinmaxParameter† 
    g l G e t P i x e l M a p
    g l G e t P o i n t e r v
    g l G e t P o l y g o n S t i p p l e
    g l G e t S e p a r a b l e F i l t e r
    g l G e t Te x E n v
    g l G e t Te x G e n
    g l G e t Te x I m a g e
    g l G e t Te x L e v e l P a r a m e t e r
    g l G e t Te x P a r a m e t e r
    注:带“†”号的例程仅当O p e n G L机制支持A R B绘图子集时才可以使用。
    如果要获取其他状态变量的值,你可以调用函数    g l G e t B o o l e a n v ( )、g l G e t D o u b l e v ( )、g l G e t F l o a t v ( )或g l G e t I n t e g e r v ( )。函数g l G e t * ( )的参考说明中介绍了如何使用这些命令。另外,你还可以使用g l G e t E r ro r ( )、g l G e t S t r i n g ( )和g l I s E n a b l e d ( )等查询命令。(与出错处理有关的例程的细节见2 . 3 . 6节“错误处理”。)你可以用函数g l P u s h A t t r i b ( )和g l P o p A t t r i b ( )来存储和恢复状态变量集。
    2.3   OpenGL实用库
    O p e n G L实用库( G L U)包含了几组命令,这些命令通过提供对辅助特性的支持,补充了核心O p e n G L界面。由于这些实用例程是使用核心的 O p e n G L命令,所以任何的 O p e n G L机制都能保证支持这些实用例程。这些实用库例程的前缀是 g l u而非gl 。
    2.3.1   生成纹理操作所需的图形
    G L U 提供了缩放图形及自动进行    m i p m a p 的例程来简化纹理图形的指定过程。例程g l u S c a l e I m a g e ( )用来将一个指定的图形缩放成一个可接受的纹理尺寸。所得的图形然后作为一个纹理传送给 O p e n G L。自动 m i p m a p例程 g l u B u i l d 1 D M i p m a p s ( )、 g l u B u i l d 2 D M i p m a p s ( )和g l u B u i l d 3 D M i p m a p s ( )将从一个指定的图形中生成一个m i p m a p的纹理图形,然后将它们分别传送给g l Te x I m a g e 1 D ( )、g l Te x I m a g e 2 D ( )和g l Te x I m a g e 3 D ( )。另外,例程g l u B u i l d 1 D M i p m a p L e v e l s ( )、g l u B u i l d 2 D M i p m a p L e v e l s ( )和g l u B u i l d 3 D M i p m a p L e v e l s ( )将为一个指定的m i p m a p图层建立一个m i p m a p纹理图形范围。
    2.3.2   坐标转换
    这里提供了几个普通用途的矩阵转换例程。你可以用例程 g l u O rt h o 2 D ( )来建立一个二维的正交观察区域,用例程 g l u P e r s p e c t i v e ( )建立一个透视观察体积,或用例程g l u L o o k A t ( )建立一个中心在指定眼点的观察体积。每个例程都建立了一个所需的矩阵,并通过函数 glMultMatrix()  将它应用于当前矩阵。
    例程g l u P i c k M a t r i x ( )通过建立一个矩阵而简化了选择操作。该矩阵用来将绘图约束到视口中的一个小区域中。如果你是在使用这个矩阵之后的选择模式下绘制图像,则光标附近所有要被绘制的对象将被选取,并且它们的相关信息将被存入选择缓冲区中。(有关选择模式的详细情况见2 . 2 . 2节“执行选择和反馈”。)

    如果你想确定在窗口的什么位置绘制物体,可以使用例程 g l u P ro j e c t ( )。该例程将把指定对象的对象坐标转换成窗口坐标,而例程 g l u U n P ro j e c t ( )和g l u U n P ro j e c t 4 ( )则执行相反的操作。
    2.3.3   多边形的镶嵌分块
    多边形镶嵌分块例程用一个或多个轮廓线将一个凹多边形分割成三角形。使用这个 G L U功能时,首先用例程g l u N e w Te s s ( )建立一个镶嵌分块的对象,并用 g l u Te s s C a l l B a c k ( )定义一个反馈例程,该例程将通过镶嵌分块器来处理三角形的生成。接下来用命令    g l u Te s s B e g i n P o l y g o n ( )、g l Te s s Ve rt e x ( )和g l Te s s E n d P o l y g o n ( )来指定将被镶嵌分块的凹多边形。你也可以在例程对g l u Te s s B e g i n P o l y g o n ( ) / g l u Te s s E n d P o l y g o n ( ) 之间使用 g l u Te s s B e g i n C o n t o u r ( ) 和g l u Te s s E n d C o n t o u r ( )来定界轮廓线。如果要删除一个不需要的镶嵌分块对象,请使用例程g l u D e l e t e Te s s ( )。
    G L U 镶嵌分块例程将把所有多边形投影到一个平面上,并镶嵌分块该投影。用命令g l u Te s s N o r m a l ( )可以为平面指定一个法线(并作为平面自身的一个结果)。如果该分块平面法线被设置为(0,0,0)—它的初始值,则命令 g l u Te s s N o r m a l ( )将基于命令g l u Te s s Ve rt e x ( )所指定的值而选取一个平面。
    2.3.4   绘制球体、圆柱和圆盘
    你可以使用 G L U的二次曲面例程来绘制球体、圆柱和圆盘。要完成这些工作,你需要首先使用g l u N e w Q u a d r i c ( )建立一个二次对象。如果你对默认值感到不满意,可以使用下面的例程来指定期望的绘制模式:
    • g l u Q u a d r i c N o r m a l s ( )决定是否应该生成表面法线。如果是,确定每个顶点都要一条法线或是否每个面上都要一条法线。
    • g l u Q u a d r i c Te x t u re ( )决定是否应生成纹理坐标。
    • g l u Q u a d r i c O r i e n t a t i o n ( )决定二次曲面的哪一边应被认为是外部,哪一边应是内部。
    • g l u Q u a d r i c D r a w S t y l e ( )决定二次曲面是否应被画成为一组多边形、线或点的集合。
    当你已经指定好绘制模式时,就可以为所希望的二次对象调用绘制例程,请用: g l u S p h e re ( )、
    g l u C y l i n d e r ( )、g l u D i s k ( )或g l u P a rt i c a l D i s k ( )。如果在绘制过程中发生了一个错误,就会触发由例程g l u Q u a d r i c C a l l B a c k ( )指定的出错处理例程。当你使用完一个二次对象后,如果想删除它,请使用g l u D e l e t e Q u a d r i c ( )。
    2.3.5   NURBS曲线和曲面
    本节描述了将 N U R B S(非归一化的有理 B样条)曲线和曲面转换到 O p e n G L的求值器的例程。
    你可以使用 g l u N e w N u r b s R e n d e re r ( )和g l u D e l e t e N u r b s R e n d e re r ( )来建立和删除一个 N U R B S对象,用g l u N u r b s C a l l B a c k ( )来建立一个错误处理例程。
    你可以用不同的例程集来指定所需的曲线和曲面。指定曲线的例程有:   g l u B e g i n C u r v e ( )、g l u N u r b s C u r v e ( )和g l u E n d C u r v e ( ),指定曲面的例程有:  g l u B e g i n S u r f a c e ( )、g l u N u r b s S u r f a c e ( )和g l u E n d C u r b s S u r f a c e ( )。你也可以指定一个修剪区域,这个区域将用来指定一个用于求值的 N U R B S曲面域的子集。这样,你便可以建立具有光滑边界或包含孔洞的曲面。这些修整例程有: g l u B e g i n Tr i m ( )、g l u P w l C u r v e ( )、g l u N u r b s C u r v e ( )和g l u E n d Tr i m ( )。
    与二次对象类似,你同样可以控制 N U R B S曲线和曲面的绘制:
    • 决定当一个曲线或曲面的控制多面体位于当前视口外时是否丢弃它们。
    • 决定用于绘制曲线和曲面的多边形边的最大长度(像素形式)。
    • 决定是将投影矩阵、模式取景矩阵和视口从  O p e n G L服务器中取走还是用 g l u L o a d S a m p l i n g M a t r i c e s ( )明确地支持它们。
    你可以使用例程 g l u N u r b s P ro p e rt y ( )来设置这些特性,或使用默认值。要查询一个  N U R B S对象的绘制模式,请使用例程 g l u G e t N u r b s P ro p e rt y ( )。
    2.3.6   错误处理
    例程 g l u E r ro r S t r i n g ( )返回一个与 O p e n G L或G L U出错代码相应的出错字符串。现有的O p e n G L出错代码在函数  g l G e t E r ro r ( )的介绍中已作了说明。有关   G L U的出错代码请参阅g l u E r ro r S t r i n g ( )、g l u Te s s C a l l b a c k ( )、g l u Q u a d r i c C a l l b a c k ( )及g l u N u r b s C a l l b a c k ( )的介绍。
    G L X例程所产生的错误在有关例程的介绍中都作了说明。
    2.4   对X窗口系统的OpenGL扩展
    在X窗口系统中, O p e n G L绘制被作为一个向正式的 X环境的 X扩展—它使用普通的 X机制实现了连接和确认。如同使用其他的 X扩展一样,有一个为被封装在 X字节流中的 O p e n G L绘制命令定义的网络协议。由于三维绘制的效率是至关重要的,因此      O p e n G L向X  的扩展允许O p e n G L忽略X服务器对数据的编码、复制和编译,而直接向图形流程绘制。
    本节简要讨论了作为 G L X一部分的例程。这些例程都带有前缀 g l X。要全面理解以下各节和成功使用G L X,你需要有一些关于 X的知识。
    2.4.1   初始化
    你可以通过例程 g l X Q u e ry E x t e n s i o n ( )和g l X Q u e ry Ve r s i o n ( )来确定是否为一个 X服务器定义了G L X扩展。如果已定义,还要确定服务器中使用的是哪个版本。如果你要决定   G L X机制的功能,请使用例程 g l X Q u e ry S e r v e r S t r i n g ( )和g l X Q u e ry E x t e n s i o n s S t r i n g ( )。它们将返回 X服务器所支持的扩展信息。例程 g l X G e t C l i e n t S t r i n g ( )描述了由G L X客户库所提供的功能。
    例程 g l X C h o o s e F B C o n f i g ( )返回一个与指定属性相匹配的  G L X F B C o n f i g的数组。用例程g l X G e t F B C o n f i g A t t r i b ( )可以返回一个与特定的 G L X F B C o n f i g相应的特定属性值,并可选取你的应用所需的最佳 G L X F B C o n f i g单元。如果你要获得一个所有可用的 G L X F B C o n f i g的完整清单,请调用例程 g l X G e t F B C o n f i g s ( )。调用例程 g l X G e t Vi s u a l F ro m F B C o n f i g ( )将获得一个与指定的G L X F B C o n f i g相应的X Vi s u a l I n f o结构。
    2.4.2   控制绘制操作
    为了使用 O p e n G L的G L X绘图,首先应该具备绘图区域和管理   O p e n G L状态所需的环境。G L X提供了几个命令用于建立、删除和管理 O p e n G L的绘图区域和绘图环境,并将它们联合起来以便实现O p e n G L的绘图功能。
    另外,还提供了附加指令用于实现 X和O p e n G L流之间的同步、交换前后缓冲区以及使用  X字体。
    1. 管理屏幕绘图区域
    要想在 O p e n G L窗口的屏幕上绘图,首先应该使用一个合适的   X可视环境建立一个 X窗口(一般使用由例程 g l X G e t Vi s u a l F ro m F B C o n f i g ( )所得到的结构 X Vi s u a l I n f o建立)。如果要将 X窗口转换成一个 G L X Wi n d o w,请使用例程 g l X C re a t Wi n d o w ( )。如果要删除一个 G L X Wi n d o w,请使用例程g l X D e s t ro y Wi n d o w ( )。
    2. 管理屏幕外的绘图区域
    G L X支持两种类型的屏幕外绘图区域: G L X P i x m a p s和G L X P b u ff e r s。G L X P i x m a p s是与一个G L X像素映射资源相应的 X像素映射。同支持 O p e n G L绘入像素映射一样,它也同样支持 X绘图。
    G L X P b u ff e r s是一个 G L X的独有资源。因此除 G L X外,其他设备不能用 X或一个 X扩展来绘制图形。
    要建立一个 G L X P i x m a p s,应首先建立一个 X像素映射,然后通过例程 g l X C re a t P i x m a p ( )将它转换成一个 G L X P i x m a p s。如果要删除一个 G L X P i x m a p s,请使用 g l X D e s t ro y P i x m a p ( ),然后还需要删除最初的 X像素映射。
    由于G L X P b u ff e r s没有相应的 X可绘区域,所以它只需要调用 g l X C re a t e P b u ff e r ( )来建立一个G L X P b u ff e r s资源。类似地,可以用 g l X D e s t ro y P b u ff e r ( )来删除G L X P b u ff e r s。
    3. 管理O p e n G L绘图环境
    例程g l X C re a t e N e w C o n t e x t ( )可以创建一个 O p e n G L绘图环境。该例程的一个自变量允许你忽略X服务器而直接申请一个绘图环境(请注意:如果要直接绘图,  X服务器必须是局部的,并且O p e n G L机制需要支持直接绘制)。你可以用 g l X I s D i re c t ( )来确定一个 O p e n G L环境是否是直接的。如果要获取G L X环境的其他属性,可调用例程 g l X Q u e ry C o n t e x t ( )。
    如果要使一个绘图环境成为当前的(将一个 G L X绘图区域与一个 G L X环境相关联),请使用g l X M a k e C o n t e x t C u r re n t ( );而 g l X G e t C u r re n t C o n t e x t ( )返回当前的环境。你也可以用g l X G e t C u r re n t D r a w a b l e ( )来获取当前的可绘区域。同样,你还可以用    g l X G e t C u r re n t ReadDrawable()  来获取当前读取的可绘区域。另外,例程 g l X G e t C u r re n t D i s p l a y ( )可以返回与X显示相关的当前可绘区域和相关环境。
    在任何时刻,对任何线程都只有一个当前环境。如果你有多个环境,你可以用     g l X C o p y C o n t e x t ( )来从一个环境向另一个环境复制所选定的 O p e n G L状态变量组。当你不再需要一个特定的环境时,请用g l X D e s t ro y C o n t e x t ( )删除它。
    4. 同步执行
    要想在任何未完成的 O p e n G L绘制结束前阻止X请求发生,请调用 g l X w a i t G L ( )。这样,任何以前发布的 O p e n G L命令将能确保在g l X w a i t G L ( )执行后所产生的X绘制调用发生之前被执行。尽管调用g l F i n i s h ( )也能得到同样的结果,但当客户端和服务器端在不同的机器上时,前者将更有效;这是因为 X服务器将等待 O p e n G L绘制的完成而不是象函数 g l F l u s h ( )那样等待客户端应用的完成。
    要想在任何未完成的 X请求完成之前阻止一个 O p e n G L命令序列的执行,请调用 g l X Wa i t X ( )。
    该例程将确保在它执行后所产生的任何O p e n G L命令执行之前首先执行以前发布的X绘制命令。
    5. 事件处理
    除了由X服务器提供的普通事件流之外,G L X还另外添加了应用中可能会处理到的其他事件。
    用例程g l X S e l e c t E v e n t ( )可以选择应用中希望被提示的 G L X事件。现在,当改变一个 G L X P b u ff e r s时只有一个G L X事件被发送。如果要返回一个 G L X事件,请调用 g l X G e t S e l e c t e d E v e n t ( )。
    6. 交换缓冲区
    对于双缓冲区的可绘环境,通过例程 g l X S w a p B u ff e r s ( )可以实现前后缓冲区的互换。一个隐含的g l F l u s h ( )将被作为这个例程的一部分来执行。
    7. 使用X字体
    命令g l X U s e X F o n t ( )为在O p e n G L中使用X字体提供了一个捷径。

    展开全文
  • 查看OpenGL版本信息

    2016-01-13 22:28:00
    查看OpenGL版本信息  执行如下代码  1 #include "stdafx.h" 2 #include <iostream> 3 #include <gl/glut.h> 4 5 int _tmain(int argc, _TCHAR* argv[]) 6 { 7 glutInit(&argc, ...
  • 安装好OpenGL的各种库后,想要在终端下编译,命令格式: g++ 文件名 -o out.o -lglut -lGL -lGLU -lm -L /usr/lib 其中 /usr/lib是OpenGL依赖文件的位置,一般默认是在/usr/lib下
  • 分类: Direct3D/OpenGL 2007-10-28 11:03 484人阅读 评论(0) 收藏 举报  扩展windowsdirect3dparametersextension微软转自... 1 opengl版本区别(在opengl官方文档中有详细说明)   
  • opengl版本

    2016-01-19 10:23:21
    1 opengl版本区别(在opengl官方文档中有详细说明)  针对Opengl不同版本的升级是主要是扩展指令集。  现在版本是4.0啦 1.1 opengl1.1 1995年,SGI推出了更为完善的OpenGL 1.1版本OpenGL 1.1的性能比1.0版...
  • linux下查看opengl版本

    千次阅读 2018-12-24 18:52:07
    //返回当前OpenGL实现的版本号 const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本 printf("OpenGL实现厂商的名字:%s\n", name); printf("渲染器标识符:%s\n", biaoshifu); ...
  • OpenGL中的绘制命令

    千次阅读 2015-08-20 14:44:50
    OpenGL中的绘制命令1.直接绘制命令OpenGL中以Draw开头的绘制命令主要分成两大类,一类是从GL_ELEMENT_ARRAY_BUFFER缓存中获取绘制信息的函数,一类是不从其获得绘制信息的函数。注意GL_ELEMENT_ARRAY_BUFFER是用于...
  • 基于OpenGL的GPU命令处理器设计方法研究.pdf
  • Chromium硬件加速渲染的OpenGL命令执行过程分析

    万次阅读 多人点赞 2015-11-09 01:00:19
    在Chromium中,由于GPU进程的存在,WebGL端、Render端和Browser...GPU进程从这个命令缓冲区读出GPU命令之后,就进行解码,然后调用对应的OpenGL函数。本文就详细分析WebGL端、Render端和Browser端执行GPU命令的过程。。
  • OpenGL的工作步骤OpenGL在屏幕上显示图形的主要步骤如下:1.构造几何要素(点、线、面、多边形、位图),创建对象的数学描述。...OpenGL命令的语法规则OpenGL的函数虽然多达几百个,但由于有一套非常规范的语法规则,应
  • linux下查看OpenGL版本

    千次阅读 2011-10-27 23:10:00
    //返回当前OpenGL实现的版本号 const GLubyte* gluVersion= gluGetString(GLU_VERSION); //返回当前GLU工具库版本 printf("OpenGL实现厂商的名字:%s\n", name); printf("渲染器标识符:%s\n", biaoshifu); ...
  • 查看opengl版本,android源码

    千次阅读 2015-06-10 22:02:19
    ActivityManager am =(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); ConfigurationInfo info = am.getDeviceConfigurationInfo(); String s = info.reqGlEsVersion+"";...
  • 【转】OpenGL版本OpenGL扩展机制

    千次阅读 2009-10-19 19:33:00
    1 opengl版本区别(在opengl官方文档中有详细说明)  针对Opengl不同版本的升级是主要是扩展指令集。  1.1 opengl1.1 1995年,SGI推出了更为完善的OpenGL 1.1版本OpenGL 1.1的性能比1.0版提高甚多。...
  • OPENGL版本介绍

    千次阅读 2006-09-08 17:19:00
    OpenGL版本比较 1 opengl版本区别(在opengl官方文档中有详细说明) 针对Opengl不同版本的升级是主要是扩展指令集。 1.1 opengl1.1 1995年,SGI推出了更为完善的OpenGL 1.1版本OpenGL 1.1的性能比1.0版提高甚多...
  • 如何察看显卡OpenGL版本

    千次阅读 2015-08-20 14:54:48
    OpenGL本身是绘图的一个工具,本身有很多版本,且向下兼容,但是OpenGL还需要操作显卡上的很多功能,所以需要显卡的驱动支持OpenGL版本,博主在用老爷机调试OpenGL的时候就遇到了这种问题,一开始摸不着头脑,后来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,079
精华内容 13,231
关键字:

opengl版本命令