OpenGL加速渲染:显示列表glGenLists

在OpenGL中,可能要用非常多的点、线、面来构成一幅图。若进行实时渲染,无疑对显示效率有非常大的影响。比如要画几百万个三角形,那么很可能旋转一下图片需要响应很久。

为了加速渲染,可以将需要绘制的部分放在显示列表glGenLists中。每一个绘制的部分都是一个显示列表成员。然后将该列表进行预编译,编译完后并不显示。当需要显示的时候,直接调用显示列表,由于已经经过了预编译,所以此时会不经编译直接显示,从而提升效率。

以一个有盖杯子为例。设杯子需要绘制的有两部分:杯盖与杯身。

使用显示列表的步骤如下:

①  定义显示列表变量作为显示列表标示符。也就是说每个绘制的部分都需要用一个标示符来标识。杯子有2个绘制部分,也就是2个标识符。

GLuint	coverList, bodyList;

注意GLuint是个int型变量。

②  申请2个显示列表名,并赋值给刚才创建的现实列表变量:

coverList = glGenLists(2);
bodyList = coverList + 1;

申请的显示列表标示符是从1开始的。也就是说,coverList==1,bodyList==2。若glGenLists返回0,则表示没有调用成功。

glGenLists就相当于C++的new操作。不要在未删除上次赋值的情况下对同一个标示符进行再次赋值。

③  为每个显示列表进行绘制操作:

glNewList(coverList, GL_COMPILE);
DrawCover();
glEndList();
glNewList(bodyList, GL_COMPILE);
DrawBody();
glEndList();

这样,就使得int型标示符与绘制函数建立了关系。调用时,只用通过int型标识     符即可调用绘制函数。

类似glBegin/glEndglNewList/ glEndList之间可以放置任意绘制函数。

④  在场景绘制函数中,通过直接调用int型标识符直接绘制即可:

glCallList(coverList);
glCallList(bodyList);

注意显示列表调用的位置。显示列表的glNewList/ glEndList必须在窗口创建后调用;一定不可以在显示函数(渲染函数/场景绘制函数)中调用;只有glCallList在场景绘制函数中调用。显示列表的glNewList/ glEndList一般会在SteupRC中调用。因为glNewList/ glEndList负责预编译工作,会对之间的函数进行编译,而该编译只需要进行一次

注意,由于使用的是预编译,所以显示列表中的部分在glNewList/ glEndList时就已经确定并编译完成了。比如在显示过程中希望更改杯体的颜色,于是直接修改了杯体的绘制函数中所使用的杯体数据,但是运行却发现杯子并没有任何变化,依然保持在glNewList/ glEndList时的状态。这是预编译造成的,预编译时是什么样子,显示时就是什么样子。即便之后更改了显示数据,但由于该数据已经编译完成,不会对新的修改再做编译了,所以修改了也没有变化。

 如果要实时反映修改的情况,那么就需要每修改一次,就重新对显示列表进行编译一个显示列表允许多次编译。若要再次编译,重新调用glNewList/ glEndList即可

调用

GLboolean glIsList(GLuint list);

函数来判断索引值是否存在。

调用

glDeleteLists(GLuint list, GLsizei range);

函数来删除多个显示列表。其中list为第一个显示列表的标示符,range 为从该标示符开始的范围。比如glDeleteLists (5,3),将从标示符5开始,删除3个显示列表,也就是删除5、6、7这三个显示列表。

当范围中的某些值非法时,会被自动忽略。

if (glIsList(m_showListGround))
{
	glDeleteLists(m_showListGround, 1);
}

glNewList/ glEndList之间是可以调用已经创建的显示列表的:

glNewList(AllList, GL_COMPILE);
glCallList(coverList);
glCallList(bodyList);
glEndList();

但不可以创建新的显示列表:

// 错误写法
glNewList(AllList, GL_COMPILE);
glNewList(coverList, GL_COMPILE);
DrawCover();
glEndList();
glEndList();

上面写法是错误的。


 关于glGenLists,其创建结果类似一个UINT数组。理论上最多创建2147483647(2^31-1)个显示列表。且一次性创建的显示列表必定是连续的

删除时,显示列表仅仅把当前位置元素删掉,并不会将后面的元素前移。比如把显示列表1、2、3中的2删除,那么1后面的2将会是个无效显示列表,但3依然保持有效。

若此时要创建新的显示列表,那么会从前向后选择合适区域创建。比如要创建2个显示列表,由于一次性创建的显示列表必连续,所以要选择有2个空区域的位置来进行创建。于是会成功创建标示符为4、5的显示列表。

此时要再次创建1个显示列表,由于2号位为空,且其大小满足1个显示列表,故而会在2号位创建新的显示列表,该列表的标示符将是2。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值