OpenGL | 显示列表

一、显示列表简介

        OpenGL显示列表(Display List)是由一组预先存储起来的留待以后调用的OpenGL函数语句组成的,当调用这张显示列表时就依次执行表中所列出的函数语句。

        使用显示列表可以提高绘制效率,节省计算机的处理资源。但OpenGL显示列表被设计成命令高速缓存,而不是动态数据库缓存。也就是说,一旦建立了显示列表,就不能修改它。(因为若显示列表可以被修改,则显示列表的搜索、内存管理的执行等开销会降低性能。)并且由于调用显示列表时程序本身也有一些开销,尤其是当一个显示列表太小会导致系统开销超过列表的优越性,所以并不是只要调用显示列表就能优化程序性能。

二、使用显示列表

        使用显示列表一般有四个步骤:分配显示列表编号、创建显示列表、调用显示列表、销毁显示列表。

1.分配显示列表编号

        为了避免自己定义的显示列表重复导致覆盖,使用glGenLists函数来自动分配一个没有使用的显示列表编号。

GLuint WINAPI glGenLists(
   GLsizei range
);

        glGenLists函数有一个参数range,表示要分配range个连续的未使用的显示列表编号。返回的是分配的若干连续编号中最小的一个。

        例如:glGenLists(3);如果返回20,则表示分配了20、21、22这三个连续的编号。如果函数返回零,表示分配失败。可以使用glIsList函数判断一个编号是否已经被用作显示列表。

2.创建显示列表

        创建显示列表实际上就是把各种OpenGL函数的调用装入到显示列表中。使用glNewList开始装入,使用glEndList结束装入。

void WINAPI glNewList(
   GLuint list,
   GLenum mode
);

glNewList有两个参数:

  • 第一个参数是一个正整数(glGenLists返回的列表编号),表示装入到哪个显示列表。
  • 第二个参数有两种取值:
    • 如果为GL_COMPILE,则表示以下的内容只是装入到显示列表,但现在不执行它们;
    • 如果为GL_COMPILE_AND_EXECUTE,表示在装入的同时,把装入的内容执行一遍。

3.调用显示列表

(1)调用一个显示列表

        调用一个显示列表使用glCallList函数,只有一个参数,即要调用的显示列表的编号,例如glCallList(10);可以调用编号为10的显示列表。

(2)调用一系列的显示列表

        使用glCallLists函数,有3个参数:

  1. 第一个参数表示要调用多少个显示列表
  2. 第二个参数表示了这些编号的存储格式:可以是GL_BYTE(每个编号用一个GLbyte表示),GL_UNSIGNED_BYTE(每个编号用一个GLubyte表示),GL_SHORT,GL_UNSIGNED_SHORT,GL_INT,GL_UNSIGNED_INT,GL_FLOAT。
  3. 第三个参数表示了这些显示列表编号的位置(数组)

        使用glCallLists前,可以用glListBase函数来设置一个偏移量。假设偏移量为k,且glCallLists中要求调用的显示列表编号依次为l1, l2, l3, …,则实际调用的显示列表为l1+k, l2+k, l3+k, …。

4.销毁显示列表

void WINAPI glDeleteLists(
   GLuint  list,
   GLsizei range
);

        使用glDeleteLists来销毁一串编号连续的显示列表。例如:使用glDeleteLists(20, 4);将销毁20,21,22,23这四个显示列表。

三、举个例子

        下方ListTest类中Init函数创建了一个显示列表,并把绘制三角形并进行贴图的工作装入其中;Draw函数调用这个显示列表。

#pragma once
#include <windows.h>   //根据OpenGL编程指南, 在包含"gl.h"头文件时, 要先包含"windows.h", 因为在gl.h里使用了windows.h中定义的标识符
#include <gl/GL.h>
#include <gl/GLU.h>
#include <gl/glext.h>
#include "texture.h"   //用来加载贴图纹理,可参考前文
class ListTest
{
private:
    int list = 0;
public:
    void Init();
    void Draw();
};
#include "ListTest.h"
void ListTest::Init()
{
   if (list == 0)
   {
       list = glGenLists(1);  //分配显示列表编号

       glNewList(list, GL_COMPILE);   //创建显示列表

       Texture texture;
       texture.Init("C:\\Users\\***\\Downloads\\272.bmp");
       glEnable(GL_TEXTURE_2D);//开启纹理
       glBindTexture(GL_TEXTURE_2D, texture.textureId);

       glBegin(GL_TRIANGLES);      

       glTexCoord2f(0.0f, 0.0f);
       glVertex3f(-0.2f, -0.2f, -1.0f);

       glTexCoord2f(1.0f, 0.0f);
       glVertex3f(0.2f, -0.2f, -1.0f);

       glTexCoord2f(0.5f, 1.0f);
       glVertex3f(0.0f, 0.2f, -1.0f);
       glEnd();

       glEndList();
   }
}

void ListTest::Draw()
{
    glCallList(list);     //调用显示列表
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值