OGL显示列表

显示列表基本知识

OGL3.1中所有显示列表相关技术和功能都废弃了。
显示列表,主要存储的是顶点数据和状态,生成显示列表后不能修改顶点数据和状态函数了,Drawcall时候,可以改变空间位置,多次调用显示列表绘制不同位置的相同物体,且可以高效的实现移动变换的动画。
可以把经常使用的函数存储在显示列表,以提高性能,有些图形硬件会把显示列表存储在专用的内存中,用一种更优的形式来存储数据,与图形硬件软件更加兼容。
OGL显示列表更像是命令缓存器,存储的是GL命令计算的结果和状态而不是过程,而不是动态数据库,因为创建后不能再修改,要修改要删掉重新生成。
显示列表的应用:
矩阵变换运算,光照材质计算每次绘制都是相同的变换设置,可以放在显示列表中,因为显示列表中存储的是最终的计算结果,而不是运算过程,因此可以有效提高性能。glLoadMatrix glMaterial*等函数是可以放置在显示列表中的。显示列表中的变换,也会对非显示列表中的绘制产生影响,因此要恰当关闭这些变换。

位图和图像进行光栅化时候,程序指定的光栅化格式不一定最适合硬件,在编译显示列表时候,OGL可能会把数据转换为最适合硬件的形式,当然为了优化纹理图像,应该把数据存储在纹理对象而不是显示列表中

一次只能创建一个显示列表,意思是不能嵌套创建。


显示列表相关函数

1.生成:

GLuint theTorus;
  theTorus = glGenLists (1); // glIsList判断一个标示符是否已经是显示列表。
// GL_COMPILE把后面的函数放在显示列表中只编译并不立即执行,Call时执行;GL_COMPILE_AND_EXECUTE编译并立即执行,Call也执行。
   glNewList(theTorus, GL_COMPILE);
/* 显示列表中存储的是当前设置的表达式结果,或存储在GPU中的顶点数组的当前解引用,后面代码中更改客户端的值并不能影响到显示列表中;服务器端的函数才可以在显示列表中设置不执行,且服务端的函数状态会影响立即模式下的状态;设置客户端状态的函数,使用了像素存储模式的函数glGetTextures等以及提取状态值的函数,依赖客户端状态的函数glFlush/glFinish等不能存储在显示列表中(所有具有返回值的函数都不能存储在显示列表中),如果在列表中应用了,会立即执行。显示列表内部不能嵌套定义显示列表,但是可以调用其它显示列表。
GLint listNetMax;
 glGetIntegerv(GL_MAX_LIST_NESTING, &listNetMax);
*/

   torus(8, 25);
// 与OGL渲染环境一起存储,渲染环境销毁时候显示列表销毁;多个窗口多渲染环境共享显示列表时候,最后一个渲染环境销毁才销毁显示列表。用glDeleteList显示的删除一组连续的显示列表,或一个。
  glEndList();

2.调用

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f (1.0, 1.0, 1.0);
// 显示列表中的执行顺序按照定义时候顺序执行,可以将空间位置变换下多次执行显示列表函数,可以和其它立即模式下的函数混合使用。不存在将显示列表保存在文件中的工具,也不存在从文件中创建显示列表,因此显示列表用于临时的设计。
   glCallList(theTorus);
   glFlush();
}

3.执行多个显示列表

base = glGenLists (128);
 glListBase(base);
base是显示列表基数,后面的glNewList,glCallLists都在当前标示符上加上基数作为真正的标识符。

实例代码:

#include <GL/glut.h>
#include <stdlib.h>
#include <string.h>

#define PT 1
#define STROKE 2
#define END 3

typedef struct charpoint {
   GLfloat   x, y;
   int    type;
} CP;

CP Adata[] = {
   { 0, 0, PT}, {0, 9, PT}, {1, 10, PT}, {4, 10, PT}, 
   {5, 9, PT}, {5, 0, STROKE}, {0, 5, PT}, {5, 5, END}
};

CP Edata[] = {
   {5, 0, PT}, {0, 0, PT}, {0, 10, PT}, {5, 10, STROKE},
   {0, 5, PT}, {4, 5, END}
};

CP Pdata[] = {
   {0, 0, PT}, {0, 10, PT},  {4, 10, PT}, {5, 9, PT}, {5, 6, PT}, 
   {4, 5, PT}, {0, 5, END}
};

CP Rdata[] = {
   {0, 0, PT}, {0, 10, PT},  {4, 10, PT}, {5, 9, PT}, {5, 6, PT}, 
   {4, 5, PT}, {0, 5, STROKE}, {3, 5, PT}, {5, 0, END}
};

CP Sdata[] = {
   {0, 1, PT}, {1, 0, PT}, {4, 0, PT}, {5, 1, PT}, {5, 4, PT}, 
   {4, 5, PT}, {1, 5, PT}, {0, 6, PT}, {0, 9, PT}, {1, 10, PT}, 
   {4, 10, PT}, {5, 9, END}
};

/*  drawLetter() interprets the instructions from the array
 *  for that letter and renders the letter with line segments.
 */
static void drawLetter(CP *l)
{
   glBegin(GL_LINE_STRIP);
   while (1) {
      switch (l->type) {
         case PT:
            glVertex2fv(&l->x);
            break;
         case STROKE:
            glVertex2fv(&l->x);
            glEnd();
            glBegin(GL_LINE_STRIP);
            break;
         case END:
            glVertex2fv(&l->x);
            glEnd();
            glTranslatef(8.0, 0.0, 0.0);
            return;
      }
      l++;
   }
}

/*  Create a display list for each of 6 characters    */
static void init (void)
{
   GLuint base;

   glShadeModel (GL_FLAT);

   base = glGenLists (128);
   glListBase(base);
   glNewList(base+'A', GL_COMPILE); drawLetter(Adata); glEndList();
   glNewList(base+'E', GL_COMPILE); drawLetter(Edata); glEndList();
   glNewList(base+'P', GL_COMPILE); drawLetter(Pdata); glEndList();
   glNewList(base+'R', GL_COMPILE); drawLetter(Rdata); glEndList();
   glNewList(base+'S', GL_COMPILE); drawLetter(Sdata); glEndList();
   glNewList(base+' ', GL_COMPILE); glTranslatef(8.0, 0.0, 0.0); glEndList();
}

char *test1 = "A SPARE SERAPE APPEARS AS";
char *test2 = "APES PREPARE RARE PEPPERS";

static void printStrokedString(char *s)
{
   GLsizei len = strlen(s);
   glCallLists(len, GL_BYTE, (GLbyte *)s);
}

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(1.0, 1.0, 1.0);
   glPushMatrix();
   glScalef(2.0, 2.0, 2.0);
   glTranslatef(10.0, 30.0, 0.0);
   printStrokedString(test1);
   glPopMatrix();
   glPushMatrix();
   glScalef(2.0, 2.0, 2.0);
   glTranslatef(10.0, 13.0, 0.0);
   printStrokedString(test2);
   glPopMatrix();
   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 ' ':
         glutPostRedisplay();
         break;
      case 27:
         exit(0);
   }
}

/*  Main Loop
 *  Open window with initial window size, title bar, 
 *  RGBA display mode, and handle input events.
 */
int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (440, 120);
   glutCreateWindow ("stroke");
   init ();
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutDisplayFunc(display);
   glutMainLoop();
   return 0;
}

4.显示列表执行时会影响后续服务器端的状态

1)不需要显示列表修改的状态
例如:当前颜色值和当前矩阵值就会影响立即模式下的绘制。
可以在显示列表定义开始时候:
glNewList()
glPushMatrix();
glPushAttrib(GL_CURRENT_BIT);
显示列表其它函数和状态修改
glPopAttrib();
glPopMatrix();
glEndList();
2)需要显示列表修改的状态。
封装模式修改
使用显示列表比使用立即模式切换GPU状态速度快;例如:不同的光照,光照模型,材料参数切换;点画模式切换;雾参数切换;裁剪平面方程切换等,因为这些状态是GPU服务器端的,而不是客户端的,因此可以保留。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值