OpenGL在即时模式(Immediate Mode)下绘图时,程序中每条语句产生的图形对象被直接送进绘图流水线,在显示终端立即绘制出来。当需要在程序中多次绘制同一个复杂的图像对象时,这种即时模式会消耗大量的系统资源,降低程序的运行效率,为此,OpenGL提供了一种更有效组织OpenGL语句的形式——显示列表

OpenGL使用显示列表方式绘图一般要比瞬时方式快,尤其是显示列表方式可以大量地提高网络性能,即当通过网络发出绘图命令时,由于显示列表驻留在服务器中,因而使网络的负担减轻到最小。另外,在单用户的机器上,显示列表同样可以提高效率。例如旋转矩阵函数glRotate*(),若将它置于显示列表中,则可大大提高性能,因为旋转矩阵的计算并不简单,包含有平方、三角函数等复杂运算,而在显示列表中,它只被存储为最终的旋转矩阵,于是执行起来如同硬件执行函数glMultMatrix()一样快。

显示列表的使用流程:建立显示列表、调用显示列表、删除显示列表

建立显示列表


分配显示列表编号

OpenGL中用正整数来区分不同的显示列表,为防止重复定义已经存在的显示列表号,使用glGenLists函数来自动分配一个没有被使用过的显示列表编号。

glGenLists函数原型:

 GLuint   glGenLists (GLsizei range);

参数range指定要分配几个显示列表。

返回值是被分配的显示列表中的最小编号,若返回0表示分配失败。

创建显示列表

创建显示列表声明了把哪些OpenGL语句装入到当前显示列表中。使用glNewList开始装入,使用glEndList结束装入。

glNewList的函数原型如下:

void   glNewList (GLuint list, GLenum mode);

第一个参数标示当前正在操作的显示列表号

第二个参数有两种取值--GL COMPILE和GL COMPILE AND EXECUTE,前者声明当前显示列表只是装入相应OpenGL语句,不执行;后者表示在装入的同时,执行一遍当前显示列表。

并不是所有的OpenGL函数都可以装入到显示列表中,一般来说,用于传递参数或具有返回数值的函数语句不能存入显示列表。

调用显示表 


调用显示列表只需要在需要调用的地方插入glCallList(id)即可,入参id表示了要调用的显示列表的编号。另外也可以使用glCallLists一次性调用一组显示列表。

删除显示表


在退出程序前要将所建立的显示表删除,释放显示列表占用的资源。

glDeleteLists(GLuint list,GLsizei range)用来删除用户建立的显示列表。

参数list表示要删除的第一个显示列表的数字编号;参数range表示从指定的第一个显示表开始要删除的连续的显示表个数。

下边是一个使用显示列表的例子,创建了两个显示列表,第一个显示列表里定义了模型视图矩阵,第二个显示列表里定义了一个矩形立方体模型,包含顶点颜色等。

调用了1次List 1,调用了3次List 2,生成了3个立体模型,运行效果:

完整代码:

#include <glut.h>
#include <Windows.h> GLfloat angle = 0.0f; void CreateDisplayLists()
{
//List 1 定义模型视图矩阵
if(!glIsList((GLuint)1))
{
glNewList(1,GL_COMPILE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75,1,2,50); glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,25,25,0,0,0,0,1,0);
glEndList();
} //List 2 定义实体矩形
if(!glIsList((GLuint)2))
{
glNewList(2,GL_COMPILE);
glBegin(GL_QUADS); //底面
glColor3f(1,0,0);
glVertex3f(-5,-5,-5);
glVertex3f(5,-5,-5);
glColor3f(0,0,1);
glVertex3f(5,5,-5);
glVertex3f(-5,5,-5);
//侧面A
glColor3f(0,0,1);
glVertex3f(-5,-5,-5);
glVertex3f(5,-5,-5);
glColor3f(0,1,0);
glVertex3f(5,-5,5);
glVertex3f(-5,-5,5);
//侧面B
glColor3f(0,1,0);
glVertex3f(5,-5,-5);
glVertex3f(5,5,-5);
glColor3f(0,1,1);
glVertex3f(5,5,5);
glVertex3f(5,-5,5);
//侧面C
glColor3f(1,1,0);
glVertex3f(5,5,-5);
glVertex3f(-5,5,-5);
glColor3f(1,0,1);
glVertex3f(-5,5,5);
glVertex3f(5,5,5);
//侧面D
glColor3f(1,0,1);
glVertex3f(-5,5,-5);
glVertex3f(-5,-5,-5);
glColor3f(0,1,0);
glVertex3f(-5,-5,5);
glVertex3f(-5,5,5);
//顶面
glColor3f(1,1,0);
glVertex3f(-5,-5,5);
glVertex3f(5,-5,5);
glColor3f(0,0,1);
glVertex3f(5,5,5);
glVertex3f(-5,5,5);
glEnd();
glEndList();
}
} void myDisplay(void)
{
glEnable(GL_DEPTH_TEST); //深度缓存
glClearColor(0.1,0.1,0.3,0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glCallList(1);
glRotatef(angle,1,0,0);
glRotatef(angle,0,1,0);
glRotatef(angle,1,0,1);
glCallList(2); //绘制模型
glTranslatef(-10,0,-10);
glCallList(2);
glTranslatef(20,0,20);
glCallList(2);
glutSwapBuffers();
} void myIdle(void)
{
angle+=0.05f;
if( angle >= 360.0f )
angle = 0.0f;
myDisplay();
} int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowPosition(200, 200);
glutInitWindowSize(400, 400);
glutCreateWindow("OpenGL");
CreateDisplayLists(); //创建显示列表
glutDisplayFunc(&myDisplay);
glutIdleFunc(&myIdle);
glutMainLoop();
return 0;
}

显示列表的适用场合


并不是所有场合下显示列表都可以优化程序性能,这是因为调用显示列表本身时程序也会产生一些开销,若一个显示列表太小,这个开销将超过显示列表的所带来的效率提升。以下是一些非常适合使用显示列表的场景:

  • 矩阵操作:大部分矩阵操作需要OpenGL计算逆矩阵,矩阵及其逆矩阵都可以保存在显示列表中。
  • 光栅位图和图像:程序定义的光栅数据不一定是适合硬件处理的理想格式。当编译组织一个显示列表时,OpenGL可能把数据转换成硬件能够接受的数据,这可能有效地提高画位的速度。
  • 光、材质和光照模型:当用一个比较复杂的光照环境绘制场景时,可以为场景中的每个物体改变材质。但是材质计算较多,因此设置材质可能比较慢。若把材质定义放在显示列表中,则每次改换材质时就不必重新计算了。因为计算结果存储在表中,因此能更快地绘制光照场景。
  • 纹理:因为硬件的纹理格式可能与OpenGL格式不一致,若把纹理定义放在显示列表中,则在编译显示列表时就能对格式进行转换,而不是执行中进行,这样就能大大提高效率。
  • 多边形的图案填充模式:可将定义的图案放在显示列表中。

OpenGL(八) 显示列表的更多相关文章

  1. NeHe OpenGL教程 第十二课:显示列表

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

  2. 第12课 OpenGL 显示列表

    显示列表: 想知道如何加速你的OpenGL程序么?这一课将告诉你如何使用OpenGL的显示列表,它通过预编译OpenGL命令来加速你的程序,并可以为你省去很多重复的代码. 这次我将教你如何使用显示列表 ...

  3. OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别

    OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...

  4. [OpenGL] 斯坦福兔子与显示列表

    1.调整桌子的大小.         在OpenGL绘制长方体,能够通过函数: glutSolidCube(Size)          绘制得到的是一个正方体,再利用缩放矩阵使其变成长方体.使得桌子 ...

  5. C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图

    C#+OpenGL+FreeType显示3D文字(1) - 从TTF文件导出字形贴图 +BIT祝威+悄悄在此留下版了个权的信息说: 最近需要用OpenGL绘制文字,这是个很费时费力的事.一般的思路就是 ...

  6. 字符图元 & 显示列表

    [字符图元] 1.typeface(字样),即设计风格,如Courier等. 2.font(字体),如10磅Courier斜体. 3.monspace即为等宽字体,proportional为非等宽字体 ...

  7. 尝试使用Osg共享渲染描述表(HGLRC)实现多线程编译显示列表--总结

    在realize()前打开预编译选项指令: osg::DisplaySettings::instance()->setCompileContextsHint(true);    mpr_osgv ...

  8. C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字

    C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字 上一篇实现了把文字绘制到OpenGL窗口,但实质上只是把含有文字的贴图贴到矩形模型上.本篇我们介绍用Poi ...

  9. C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字

    C#+OpenGL+FreeType显示3D文字(2) - 用GLSL+VBO绘制文字 +BIT祝威+悄悄在此留下版了个权的信息说: 上一篇得到了字形贴图及其位置字典(可导出为XML).本篇就利用此贴 ...

随机推荐

  1. Mysql错误: ERROR 1205: Lock wait timeout exceeded解决办法(MySQL锁表、事物锁表的处理方法)

    Java执行一个SQL查询未提交,遇到1205错误. java.lang.Exception: ### Error updating database.  Cause: java.sql.SQLExc ...

  2. 浅谈java中异常抛出后代码是否会继续执行

    问题 今天遇到一个问题,在下面的代码中,当抛出运行时异常后,后面的代码还会执行吗,是否需要在异常后面加上return语句呢? public void add(int index, E element) ...

  3. 【Heritrix基础教程之1】在Eclipse中配置Heritrix 分类: H3_NUTCH 2014-06-01 00:00 1262人阅读 评论(0) 收藏

    一.新建项目并将Heritrix源码导入 1.下载heritrix-1.14.4-src.zip和heritrix-1.14.4.zip两个压缩包,并解压,以后分别简称SRC包和ZIP包: 2.在Ec ...

  4. php实现 合唱队形(算法想清楚在动)

    php实现  合唱队形(算法想清楚在动) 一.总结 一句话总结:写一个最长递增子序列的函数,正反两遍扫一下就好.写函数这样不容易错.这个好像可以用二分来优化. 1.算法题怎么提高正确率和节约时间? 算 ...

  5. 高性能 Python —— vectorization

    首先来看一段判断一个整数数是否为素数的函数,然后从计算机内部计算流程的角度对其进行分析: import math def check_prime(number): sqrt_number = math ...

  6. ArcGIS Engine 编辑介绍

    转自原文 ArcGIS Engine 编辑介绍 IWorkspaceEdit接口是ArcGIS Engine 实现空间数据编辑的重要接口,它让程序启动或者停止一个编辑流程,在这个编辑流程内,可以对数据 ...

  7. [Typescript] Generics using TypeScript

    In this lesson we cover the key reason why programming languages need generics. We then show how use ...

  8. 编译nodejs及其源代码研究

    本文将从 源代码 研究nodejs 的原理.本质,探讨nodejs的应用场景,以及高性能开发实践指南. 文件夹: 第一节:编译node.js 第二节:源代码分析 进入主题:下面是在win7 64 下进 ...

  9. [Vue] Use Vue.js Component Computed Properties

    You can add computed properties to a component to calculate a property on the fly. The benefit of th ...

  10. Android-通过Java代码来实现属性动画

    Android-通过Java代码来实现属性动画 除了能够使用定义xml文件来设置动画之外.还能够使用java代码来进行控制动画. 示比例如以下: 布局文件: <RelativeLayout xm ...