嵌套显示列表
为了支持更加复杂的绘图,显示列表还支持嵌套,即在glNewList()和glEndList()创建显示列表的过程中使用glCallList()或glCallLists()调用已经定义过的显示列表。生成列表的嵌套层数从理论上来说可以支持2^31-2级,但是实际上有两个原因无法支持这么多,一是当嵌套层数增加较多时,仅仅创建显示列表就需要耗费大量的资源和时间;二是即便可以创建多级嵌套,但超过64级OpenGL就不再显示了。另外,使用glGetIntegerv(GL_MAX_LIST_NESTING, &level)可以得到level的值是64,因此超过64级的显示列表嵌套其实是没有意义的。不过64层嵌套已经完全可以满足我们的应用程序的需要了。
下面我们利用嵌套来实现一个奥林匹克五环旗图案。
void CreateLists()
{
list = glGenLists(3);
if(list)
{
//第一个显示列表绘制10个立方体
glNewList(list, GL_COMPILE);
for(int i=0; i<10; i++)
{
glPushMatrix();
glRotatef(36*i,0.0,0.0,1.0) ;
glTranslatef(10.0,0.0,0.0) ;
DrawCube();
glPopMatrix();
}
glEndList();
//第二个显示列表很简单,仅仅画一线段
glNewList(list+1, GL_COMPILE);
for(i=0; i<20; i++)
{
glPushMatrix();
glRotatef(18*i,0.0,0.0,1.0) ;
glTranslatef(15.0,0.0,0.0) ;
glBegin(GL_LINES);
glVertex3f(-1, 0,0);
glVertex3f(1,0,0);
glEnd();
glPopMatrix();
}
glEndList();
//这里开始的第三个显示列表嵌套了前面两个显示列表
glNewList(list+2, GL_COMPILE);
for(i=0; i<3; i++) //上面三个圆环
{
glPushMatrix();
glTranslatef(25*i, 0, 0);
glCallList(list); //第一个显示列表
glCallList(list+1); //第二个显示列表
glPopMatrix();
}
for(i=0; i<2; i++) //下面两个圆环
{
glPushMatrix();
glTranslatef(12,0,0);
glTranslatef(25*i, -10, 0);
glCallList(list);
glCallList(list+1);
glPopMatrix();
}
glEndList();
}
}
void glMain()
{
static int angle =0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); //加载单位矩阵
glTranslatef(-25.0f, 0.0f, -80.0f);
glBindTexture(GL_TEXTURE_2D, g_Texture[0]); // 选择纹理
glCallList(list+2);
angle++;
SwapBuffers(g_hDC);//交换前后缓冲区
}
程序运行结果是5个圆环组成五环图案,每个圆环由10个立方体组成,并且在圆环外面围绕着类似发光的线段,效果如图6-3所示。
其实绘制圆环使用auxSolidTorus()更加方便,不过这里是为了说明嵌套显示列表的调用。