
8.4. Дисплейные списки
Дисплейный список – это группа команд OpenGL, сохраненная для дальнейшего исполнения. Когда исполняется дисплейный список, команды, включенные в него, исполняются в том порядке, в котором они были заданы.
Во всех примерах программ до этого момента все команды OpenGL исполнялись в непосредственном режиме, т.е. выполнялись немедленно.
Дисплейные списки могут увеличить быстродействие благодаря сохранению списков команд в специально выделенной для этого памяти и в оптимизированной форме. При этом исключены непосредственные вызовы команд OpenGL, что тоже позволяет увеличить быстродействие.
Определение дисплейного списка начинается вызовом команды, прототип которой void glNewList(GLuint list, GLenum mode) и завершается void glEndList(). Все команды, находящиеся между этими двумя вызовами, сохраняются в дисплейном списке (хотя некоторые из команд OpenGL вообще не могут быть сохранены там). В команде glNewList параметр list представляет собой положительное целое число, используемое в дальнейшем для идентификации дисплейного списка. Параметр mode определяет режим сборки группы команд и может принимать значения GL_COMPILE и GL_COMPILE_AND_EXECUTE. В первом случае команды только накапливаются в списке, во втором команды сначала выполняются и только потом заносятся в список.
При создании списка следует быть осторожными, чтобы случайно не задействовать уже используемый индекс, поскольку это приведет к перезаписи имеющегося списка. Во избежание этой проблемы можно использовать функцию с прототипом GLuint glGenLists(GLsizei range) для генерирования одного или более незадействованных индексов. В этой функции параметр range определяет число генерируемых незадействованных индексов, которые начинаются с числа, возвращаемого этой функцией.
Для удаления неиспользуемых дисплейных списков используется команда с прототипом void glDeleteLists(GLuint list, GLsizei range), которая удаляет последовательные (по индексам) списки количеством range, начиная с индекса list.
Дисплейные списки могут включать в себя и команды для установки состояния, и команды рисования. Они хранятся на сервере и могут быть обработаны позже вызовами команд с прототипами void glCallList(GLuint list), void glCallLists(GLsizei n, GLenum type, const GLvoid *lists), где list – это идентификатор дисплейного списка, созданного командой glNewList; n – количество списков в массиве lists для выполнения; type – тип значений в массиве lists. Параметр type может принимать значения, приведенные в табл. 8.2. Параметр list содержит адрес массива идентификаторов дисплейных списков.
Таблица 8.2
Значения и смысл параметра type
type |
Массив параметра list |
GL_BYTE |
Массив байтов из диапазона [–128, 127] |
GL_UNSIGNED_BYTE |
Массив неотрицательных байтов [0, 255] |
GL_SHORT |
Массив двухбайтовых целых [–32768, 32767] |
GL_UNSIGNED_SHORT |
Массив неотрицательных двухбайтовых целых |
GL_INT |
Массив четырехбайтовых целых |
GL_UNSIGNED_INT |
Массив неотрицательных четырехбайтовых целых |
GL_FLOAT |
Массив четырехбайтовых вещественных значений |
GL_2_BYTES |
Массив байтов (без знака), причем каждая пара байтов определяет единственное имя списка изображений |
GL_3_BYTES |
Массив байтов (без знака), причем каждая тройка байтов определяет единственное имя списка изображений |
GL_4_BYTES |
Массив байтов (без знака), причем каждая четверка байтов определяет единственное имя списка изображений |
В листинге 8.5 приводится фрагмент кода рисования полигональной сетки из предыдущего раздела.
Листинг 8.5. Пример использования дисплейного списка.
GLuint list = 0;
void init()
{ ………………………
list = glGenLists(1); //Генерация незадействованного индекса списка
glNewList(list, GL_COMPILE); //Создание списка и накопление команд
//грань 0
glBegin(GL_POLYGON);
glNormal3f(0.577, 0.577, 0.577);
glVertex3f(1, 0, 0);
glVertex3f(0, 1, 0);
glVertex3f(0, 0, 1);
glEnd();
………………………
glEndList(); //Завершение накопления команд в списке
}
void display()
{ ……………………..
glPushMatrix();
glRotatef(45.0, 0.0, 1.0, 0.0);
glCallList(list); //Вызов списка накопленных ранее команд
glPopMatrix();
……………………..
glutSwapBuffers();
}