使用显示列表一般有四个步骤:分配显示列表编号、创建显示列表、调用显示列表、销毁显示列表。
一、分配显示列表编号OpenGL允许多个显示列表同时存在,就好象C语言允许程序中有多个函数同时存在。C语言中,不同的函数用不同的名字来区分,而在OpenGL中,不同的显示列表用不同的正整数来区分。
你可以自己指定一些各不相同的正整数来表示不同的显示列表。但是如果你不够小心,可能出现一个显示列表将另一个显示列表覆盖的情况。为了避免这一问题,使用glGenLists函数来自动分配一个没有使用的显示列表编号。
glGenLists函数有一个参数i,表示要分配i个连续的未使用的显示列表编号。返回的是分配的若干连续编号中最小的一个。例如,glGenLists(3);如果返回20,则表示分配了20、21、22这三个连续的编号。如果函数返回零,表示分配失败。
可以使用glIsList函数判断一个编号是否已经被用作显示列表。
二、创建显示列表创建显示列表实际上就是把各种OpenGL函数的调用装入到显示列表中。使用glNewList开始装入,使用glEndList结束装入。glNewList有两个参数,第一个参数是一个正整数表示装入到哪个显示列表。第二个参数有两种取值,如果为GL_COMPILE,则表示以下的内容只是装入到显示列表,但现在不执行它们;如果为GL_COMPILE_AND_EXECUTE,表示在装入的同时,把装入的内容执行一遍。
例如,需要把“设置颜色为红色,并且指定一个坐标为(0, 0)的顶点”这两条命令装入到编号为list的显示列表中,并且在装入的时候不执行,则可以用下面的代码:
glNewList(list, GL_COMPILE);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glEnd();
注意:显示列表只能装入OpenGL函数,而不能装入其它内容。例如:
int i = 3;
glNewList(list, GL_COMPILE);
if( i > 20 )
glColor3f(1.0f, 0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
glEnd();
其中if这个判断就没有被装入到显示列表。以后即使修改i的值,使i>20的条件成立,则glColor3f这个函数也不会被执行。因为它根本就不存在于显示列表中。
另外,并非所有的OpenGL函数都可以装入到显示列表中。例如,各种用于查询的函数,它们无法被装入到显示列表,因为它们都具有返回值,而glCallList和glCallLists函数都不知道如何处理这些返回值。在网络方式下,设置客户端状态的函数也无法被装入到显示列表,这是因为显示列表被保存到服务器端,各种设置客户端状态的函数在发送到服务器端以前就被执行了,而服务器端无法执行这些函数。分配、创建、删除显示列表的动作也无法被装入到另一个显示列表,但调用显示列表的动作则可以被装入到另一个显示列表。
三、调用显示列表使用glCallList函数可以调用一个显示列表。该函数有一个参数,表示要调用的显示列表的编号。例如,要调用编号为10的显示列表,直接使用glCallList(10);就可以了。
使用glCallLists函数可以调用一系列的显示列表。该函数有三个参数,第一个参数表示了要调用多少个显示列表。第二个参数表示了这些显示列表的编号的储存格式,可以是GL_BYTE(每个编号用一个GLbyte表示),GL_UNSIGNED_BYTE(每个编号用一个GLubyte表示),GL_SHORT,GL_UNSIGNED_SHORT,GL_INT,GL_UNSIGNED_INT,GL_FLOAT。第三个参数表示了这些显示列表的编号所在的位置。在使用该函数前,需要用glListBase函数来设置一个偏移量。假设偏移量为k,且glCallLists中要求调用的显示列表编号依次为l1, l2, l3, ...,则实际调用的显示列表为l1+k, l2+k, l3+k, ...。
例如:
GLuint lists[] = {1, 3, 4, 8};
glListBase(10);
glCallLists(4, GL_UNSIGNED_INT, lists);
则实际上调用的是编号为11, 13, 14, 18的四个显示列表。
注:“调用显示列表”这个动作本身也可以被装在另一个显示列表中。
四、销毁显示列表销毁显示列表可以回收资源。使用glDeleteLists来销毁一串编号连续的显示列表。
例如,使用glDeleteLists(20, 4);将销毁20,21,22,23这四个显示列表。
=====================未完,请勿跟帖=====================