В начале работы вызывается процедура инициализации, где создается (описывается) дисплейный список:
const
listName : GLUint = 1; // идентификатор списка
procedure init;
begin
glNewList (listName, GL_CCMPILE}; // начало описания списка
glColor3f (1.0, 0.0, 0.0);
glBegin (GL_TRIANGLES);
glVertex2f (0.0, 0.0);
glVertex2f (1.0, 0.0);
glVertex2f (0.0, 1.0);
glEnd;
glTranslatef (1.5, 0.0, 0.0);
glEndList; // конец описания списка
end;
Описание списка начинается с вызова команды glNewList, первым аргументом которой является целочисленный идентификатор - имя списка (в примере именем служит константа). Вторым аргументом команды является символическая константа; здесь мы указываем системе OpenGL на то, что список компилируется для возможного последующего использования. Все следующие до glEndList команды OpenGL и образуют дисплейный список, единую последовательность.
В данном примере в списке задается красный цвет примитивов, далее следуют команды для построения одного треугольника, заканчивается список Переносом системы координат по оси X.
В коде воспроизведения кадра цвет примитивов задается зеленым, затем десять раз вызывается описанный список.
glColor3f (0.0, 1.0, 0.0); // текущий цвет - зеленый
glPushMatrix; // запомнили систему координат
For i := 0 to 9 do // десять раз вызывается список с именем
glCallList (listName);
drawLine; // построить отрезок
glPopMatixx; // вернулись в запоганенную систему координат
Списки вызываются командой glcallList, единственным аргументом которой является идентификатор вызываемого списка.
В примере после каждого вызова списка номер один система координат смещается, поэтому на экране получается ряд треугольников, а отрезок рисуется вслед за последним треугольником. Хотя цвет примитивов задается зеленым, в списке он переустанавливается в красный, поэтому отрезок рисуется именно таким цветом.
Новички часто путаются, считая дисплейные списки полной аналогией подпрограмм. Отличает списки от подпрограмм то, что списки не имеют параметров, команды при вызове списка действуют точно так же, как и при создании списка. Если при описании списка используются переменные, то при вызове списка значения этих переменных никак не используются. Впрочем, ряд команд, помещенных в список, при вызове будут отрабатываться каждый раз заново, в документации приведен список таких команд.
Замечание
Я много раз встречал утверждение, что использование списков эффективно по причине того, что компиляция их приводит к более быстрому выполнению - в списке не запоминаются промежуточные команды. Если это и так, то ощутить "на глаз" ускорение работы приложения при использовании дисплейных списков как-то не получается. Тем не менее, я настоятельно рекомендую их использовать, это приводит к повышению читабельности и упрощению кода.
По окончании работы память, занятую списками, необходимо освобождать, как это делается в этом примере:
glDeleteLists (listNamer 1);
Первый аргумент команды - имя первого удаляемого списка, второй параметр - количество удаляемых списков. Удаляются все списки, следующие за указанным. Стоит напомнить, что удалять списки необходимо до освобождения контекста воспроизведения.
В продолжение темы рассмотрим проект из подкаталога Ех56, Результат работы приложения приведен на Рисунок 3.34.