Вы находитесь на странице: 1из 40

Компьютерная

графика

лекция 6
Списки Отображения (Display Lists)

• Используя список отображения, вы


создаете объект лишь один раз.
• Вы можете текстурировать его,
раскрасить его.
• Вы даете списку название.
Плюсы от использования списков
отображения

Так как объект уже создан в списке


отображения, не нужно указывать OpenGL,
как создать его. Он уже создан в памяти. Это
снижает нагрузку на процессор и позволяет
вашим программам выполняться быстрее.
Списки отображения
Списки отображения могут увеличить
быстродействие, поскольку вы можете сохранять в
них команды OpenGL для дальнейшего
исполнения.

Хорошей идеей является кэширование команд в


списке отображения, если вы планируете рисовать
какую-либо геометрию несколько раз или если
несколько раз устанавливаете одно и то же
состояние настроек.

Используя списки отображения, вы можете


определить геометрические данные или изменения
в состоянии один раз и затем исполнять их столько
раз, сколько вам нужно.
Создание списков отображения
GLuint glGenLists (GLsizei range);

glGenLists(n) - создает место для n списков,


и возвращает указатель на первый из них.

box=glGenLists(2);
box будет хранить расположение первого
списка. Всякий раз при вызове box будет
нарисован первый список.
Создание списков отображения
void glNewList (GLuint list, GLenum mode);
Маркирует начало списка отображения

void glEndList (void);


Маркирует конец списка отображения
Создание списков отображения
glNewList(box,GL_COMPILE);    
Первый параметр - место хранения списка,
на которое указывает переменная box.
Второй параметр GL_COMPILE говорит
OpenGL, что мы хотим предварительно
создать список в памяти, таким образом,
OpenGL не будет вычислять, как создать
объект, всякий раз как мы хотим нарисовать
его.
Вызов списка отображения

void glCallList (GLuint list);

glCallList(box);
Эта команда исполняет список отображения,
заданный аргументом box. Команды в списке
исполняются в том порядке, в котором они
сохранялись, таким же образом, как если бы
они выполнялись вне списка.
Создание списков отображения
GLvoid BuildLists() //создаем список отображения
{
GLuint quad;
box=glGenLists(2); //создаем два списка
quad = box + 1;
glNewList(quad,GL_COMPILE); // Новый откомпилированный список
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0, 0, 0);
glTexCoord2f(0, 1);
glVertex3f(0, 1, 0);
glTexCoord2f(1, 1);
glVertex3f(1, 1, 0);
glTexCoord2f(1, 0);
glVertex3f(1, 0, 0);
glEnd(); // Закончили рисование четырехугольников
glEndList(); // Закончили создание списка
Создание списков отображения
glNewList(box,GL_COMPILE); // Новый откомпилированный список box
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnable (GL_TEXTURE_2D);
glPushMatrix();
glTranslated(-0.5, -0.5, -0.5);
glCallList(quad);
glTranslated(0, 0, 1);
glCallList(quad);
glRotated(90, 0, 1, 0);
glCallList(quad);
glTranslated(0, 0, 1);
glCallList(quad);
glTranslated(0, 1, -1);
glRotated(90, 1, 0, 0);
glBindTexture(GL_TEXTURE_2D, texture[1]);
glCallList(quad);
glTranslated(0, 0, 1);
glCallList(quad);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glEndList(); // Закончили создание списка box
glCallList(box);
Вывод списков отображения
glPushMatrix();
int n = 5;
int m = 5;
for (int j = -n; j<=n; j++)
for (int i = -m; i<=m; i++)
{
glPushMatrix();
glTranslated(i, j, 0);
glCallList(box);
glPopMatrix();
}
glPopMatrix();
Создание списков отображения
Вы можете написать любую команду, какую
только захотите, между glNewList() и
glEndList().
Вы можете задавать цвета, менять текстуры
и т.д.
Единственный тип кода, который вы не
можете использовать - это код, который
изменит список отображения "на лету".
Однажды создав список отображения, вы не
можете его изменить.
Вывод списков отображения
glPushMatrix();
int n = 5; int m = 5;
int mas[6][3] = {{1,0,0},{0,1,0},{0,0,1},{1,1,0},{0,1,1},{1,0,1}};
for (int j = 0; j<=n; j++)
{ for (int i = -m; i<=m; i++)
for (int k = -m; k<=m; k++)
{ glPushMatrix();
glTranslated(i, j, k);
glColor3d(mas[m][0],mas[m][1],mas[m][2]);
glCallList(box);
glPopMatrix();
}
m--;
}
glPopMatrix();
Пример использования списков
отображения
Иерархические списки отображения

Можно создать иерархический список


отображения, то есть список отображения,
который исполняет другой список
отображения, вызывая glCallList() между
парой glNewList() и glEndList().

Иерархический список отображения полезен


для рисования объектов, состоящих из
компонентов, особенно если эти компоненты
используются более одного раза.
Пример иерархии списков

glNewList(listIndex, GL_COMPILE);
glCallList(handlebars);
glCallList(frame);
glTranslatef(1.0,0.0,0.0);
glCallList(wheel);
glTranslatef(3.0,0.0,0.0);
glCallList(wheel);
glEndList();
Иерархические списки отображения

Во избежание бесконечной рекурсии существует


ограничение на уровень вложенности списков
отображение.
Выяснить максимальный уровень вложенности в
вашей реализации OpenGL, используйте:

glGetIntegerv(GL_MAX_LIST_NESTING, GLint *data);


Удаление списков отображения
Вы можете удалить конкретный список
отображения или их непрерывный диапазон
командой glDeleteLists(). После применения
glDeleteLists(), индексы удаленных списков
становятся доступны для дальнейшего
использования.
void glDeleteLists (GLuint list, GLsizei range);
Удаляет последовательные (по индексам)
списки отображения количеством range,
начиная с индекса list.
Создание растрового шрифта
HFONT CreateFont(
int nHeight, // высота шрифта

int nWidth, // средняя ширина символа

int nEscapement, // угол наклона

int nOrientation, // угол ориентации базисной линии

int fnWeight, // толщина шрифта


Создание растрового шрифта
DWORD fdwItalic, // описатель параметра
курсивного шрифта

DWORD fdwUnderline, // описатель параметра


подчеркивания

DWORD fdwStrikeOut, // описатель параметра


зачеркивания

DWORD fdwCharSet, // идентификатор набора


символов

DWORD fdwOutputPrecision, // точность вывода


Создание растрового шрифта
DWORD fdwClipPrecision, // точность отсечения

DWORD fdwQuality, // качество вывода

DWORD fdwPitchAndFamily, // шаг между


символами шрифта и семейство

LPCTSTR lpszFace // имя шрифта


);
Пример создания шрифта
font = CreateFont( -24, // Высота фонта
0, // Ширина фонта
0, // Угол отношения
0, // Угол наклона
FW_BOLD, // Ширина шрифта
FALSE, // Курсив
FALSE, // Подчеркивание
FALSE, // Перечеркивание
ANSI_CHARSET, // Идентификатор набора символов
OUT_TT_PRECIS, // Точность вывода
CLIP_DEFAULT_PRECIS, // Точность отсечения
ANTIALIASED_QUALITY, // Качество вывода
FF_DONTCARE|DEFAULT_PITCH, // Семейство и шаг
L"Courier New"); // Имя шрифта
Вывод текста разными шрифтами
Создание растрового шрифта
GLuint base; // База списка отображения для фонта
GLvoid BuildFont(GLvoid) // Построение нашего растрового шрифта
{ HFONT font; // Идентификатор фонта
base = glGenLists(256); // Выделим место для 256 символов
font = CreateFont( 16, 8, // Высота фонта // Ширина фонта
0, // Угол отношения
0, // Угол наклона
FW_BOLD, // Ширина шрифта
FALSE, // Курсив
FALSE, // Подчеркивание
FALSE, // Перечеркивание
ANSI_CHARSET, // Идентификатор набора символов
OUT_TT_PRECIS, // Точность вывода
CLIP_DEFAULT_PRECIS, // Точность отсечения
ANTIALIASED_QUALITY, // Качество вывода
FF_DONTCARE|DEFAULT_PITCH, // Семейство и шаг
"Arial"); // Имя шрифта
Создание растрового шрифта

SelectObject(auxGetHDC(), font); // Выбрать шрифт,


wglUseFontBitmaps(auxGetHDC(), 0, 256, base); // Построить 256
символов начиная c 0

}
Удаление растрового шрифта

GLvoid KillFont(GLvoid)
{
glDeleteLists(base, 256);
}
Вывод текста растровым шрифтом
GLvoid glPrint(float x, float y, float z, char text[256])
{
glPushMatrix();
glTranslated(x, y, z);
glRasterPos2f(0, 0); // Позиционирование текста на экране

glPushAttrib(GL_LIST_BIT); // Протолкнуть биты списка


отображения
glListBase(base); // Задать базу символов в 0

glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Текст


списками отображения, количество списков, тип индексов,
индексы списков

glPopAttrib(); // Возврат битов списка отображения


glPopMatrix();
}
Пример вызова функции вывода текста

glPrint(0, 0, 0, "Hello, world!");

glPrint(0, -4, 0, "Hello,");


glPrint(0, -6, 0, "world!");
Создание векторного шрифта
GLuint basev; // База списка отображения для фонта
GLYPHMETRICSFLOAT gmf[256]; // Массив с информацией шрифте
GLvoid BuildVectorFont(GLvoid) // Строим растровый шрифт
{ HFONT font; // Идентификатор шрифта Windows
base = glGenLists(256); // массив для 256 букв
font = CreateFont( 100, // высота шрифта
0, // ширина знакоместа
0, //Угол перехода
0, //Угол направления
FW_BOLD, //Ширина шрифта
FALSE, // Курсив
FALSE, // Подчеркивание
FALSE, // Перечеркивание
ANSI_CHARSET, //Идентификатор кодировки
OUT_TT_PRECIS, // Точность вывода
CLIP_DEFAULT_PRECIS, //Точность отсечения
ANTIALIASED_QUALITY,// Качество вывода
FF_DONTCARE|DEFAULT_PITCH, // Семейство и Шаг
"Courier New"); // Имя шрифта
Создание векторного шрифта
SelectObject(auxGetHDC(), font); //Выбрать шрифт, созданный нами

wglUseFontOutlines( auxGetHDC(), // Выбрать текущий контекст


устройства (DC)
0, // Стартовый символ
256, // Количество создаваемых списков отображения
base, // Стартовое значение списка отображения
0.0f, //Отклонение от настоящего контура
0.5f, //Толщина шрифта по оси Z
WGL_FONT_LINES,
//Использовать линии, или полигоны(WGL_FONT_POLYGONS)
gmf); //буфер адреса для данных списка отображения
}
Вывод текста векторным шрифтом
GLvoid glPrintV(float x, float y, float z, char text[256], float ax,
float ay, float az, float r, float g, float b)
{
float length=0; // Переменная для нахождения
glPushMatrix();
for (unsigned int loop=0;loop<(strlen(text));loop++)//Цикл
поиска размера строки
{
length+=gmf[(unsigned char)text[loop]].gmfCellIncX;
// Увеличение размера на ширину символа
}
glTranslated(x, y, z);
glRotatef(ax,1.0f,0.0f,0.0f); // Поворот по оси X
glRotatef(ay,0.0f,1.0f,0.0f); // Поворот по оси Y
glRotatef(az,0.0f,0.0f,1.0f); // Поворот по оси Z
Вывод текста векторным шрифтом
GLvoid glPrintV(float x, float y, float z, char text[256], float ax,
float ay, float az, float r, float g, float b)
{
glTranslated(-length/2, 0, 0);
glColor3f(r, g, b);
glRasterPos2f(0, 0); // Позиционирование текста на экране
glPushAttrib(GL_LIST_BIT); // Протолкнуть биты списка

glListBase(base);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);// Текст
списками отображения

glPopAttrib(); // Возврат битов списка отображения


glPopMatrix();
}
Вывод текста векторным шрифтом
Вывод текста векторным шрифтом линиями
Вывод текста векторным шрифтом полигонами
Расчет FPS
Frames Per Second — количество кадров в секунду на экране
монитора
float fps;
int frameCount=0;
int lastTimeCalcfps=0;

void CalcFPS()
{ frameCount++; // количество кадров отрисовки
unsigned int t = GetTickCount(); // текущее время
// если прошло больше секунды, то пересчитываем fps
if (t - lastTimeCalcfps>1000)
{
fps = frameCount;
frameCount = 0;
lastTimeCalcfps = t;
}
}
Вывод на экран значение FPS
void DrawFPS()
{
char buffer[20];
char *p; // указатель на результат
p = itoa(int(fps), buffer, 10);
glPrint(0, 10, -10, "FPS");
glPrint(2, 10, -10, buffer);
}