显示列表基本知识
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服务器端的,而不是客户端的,因此可以保留。
9284

被折叠的 条评论
为什么被折叠?



