Кафедра: Информационные технологии
Трехмерная графика OpenGL
1.1 Подключение графической библиотеки OpenGL к интерфейсу Windows
Стандарт реализации OpenGL для Windows требует выполнения некоторых настроек, связанных с особенностями операционной системы. Для того чтобы оконная система могла работать с OpenGL, необходимо провести ее инициализацию и сконфигурировать буфер фрейма.
Система OpenGL, как и любое другое приложение Windows, нуждается в ссылке на окно, на котором будет осуществляться воспроизведение. Ссылка на контекст воспроизведения – величина типа HGLRC (Handle to OpenGL Rendering Context) – связывает OpenGL с оконными системами Windows.
Для получения этого контекста OpenGL нуждается в величине типа HDC (контекст устройства) окна, на который будет осуществляться вывод.
Таким образом, чтобы начать работать с командами OpenGL, приложение должно создать один или несколько контекстов воспроизведения для потока, и сделать текущим один из них. Каждый поток при этом может иметь один и только один текущий контекст воспроизведения, который ассоциирован с определённым контекстом устройства.
Прежде чем получить контекст воспроизведения, сервер OpenGL должен получить детальные характеристики используемого оборудования. Эти характеристики хранятся в специальной структуре, тип которой TPixelFormatDescriptor (описание формата пикселей). Формат пикселей определяет число бит на пиксел, конфигурацию буфера цвета и вспомогательных буферов используемых для вывода изображения.
Для установки формата пикселей необходимо написать соответствующую процедуру, типичный пример которой приведён в приложении 2.
Для работы с контекстом воспроизведения в Win32 API реализованы следующие функции.
Функция создаёт контекст воспроизведения OpenGL, который подходит для рисования на устройстве, определённом дескриптором dc. При успешном завершении функция возвращает дескриптор созданного контекста воспроизведения OpenGL, и NULL – в случае неудачи.
Текущий контекст воспроизведения потока должен быть единственным. Следующая функция позволяет определить контекст воспроизведения для контекста устройства.
При завершении работы, необходимо, чтобы контекст никем не использовался. Для этого достаточно выполнить вызов функции:
Завершая работу с OpenGL необходимо удалить контекст воспроизведения. Для этой цели используется функция:
После того как удалён контекст воспроизведения, следует удалить и ассоциированный с ним контекст устройства.
Структуру приложения, использующего OpenGL, можно изобразить в виде схемы (рис. 1)
1.2 Синтаксис команд OpenGL
Для того чтобы команды OpenGL были доступны в проекте, необходимо указать библиотеку в списке используемых модулей.
Все команды начинаются с префикса gl, затем идёт имя команды, цифра и суффикс. Цифра в окончании соответствует количеству аргументов, буква показывает требуемый тип аргумента.
Если имя команды заканчивается на v (векторная форма), то аргументом её служит указатель на массив значений.
Например: Если последние три символа в имени команды 3fv, то её аргумент – адрес массива трёх вещественных чисел.
В общем виде команду можно представить:
glCommandName {1,2,3,4} {b, s, i, f, d, ub, us, ui} {v} (arguments)
Таблица 1.1. Возможные типы аргументов
Символ | Обозначение типа в OpenGL | Расшифровка |
b | GLbyte | Байтовый |
s | GLshort | Короткий целый |
i | GLint | Целый |
d | GLdouble | Вещественный двойной точности |
f | GLfloat | Вещественный |
ub | GLubyte | Байтовый, беззнаковый |
us | GLushort | Короткий целый, беззнаковый |
ui | GLuint | Целый, беззнаковый |
Почти всегда предпочтительно использовать команду в вещественной форме, поскольку хранит данные OpenGL именно в вещественном формате.
Процедура рисования заключается в командные скобки
glBegin(mode)
… // команды, указывающие вершины фигуры
glEnd;
Главное назначение командных скобок – это задание режима, определяющего как соединять точки (вершины). Вершины задаются своими координатами (количество координат зависит от пространства изображения) с помощью команд glVertex {2,3,4} {s, i, f, d} (arg).
Режим (mode), задающий правило соединения точек, определяет примитив. К примитивам относятся точки, линии, связанные линии, замкнутые линии, треугольники, связанные треугольники, четырёхугольники, связанные четырёхугольники и многоугольники.
Пример: задание стороны куба
glBegin (GL_POLYGON);
glNormal3f (0.0, 0.0, 1.0);
glVertex3f (1.0, 1.0, 1.0);
glVertex3f (-1.0, 1.0, 1.0);
glVertex3f (-1.0, -1.0, 1.0);
glVertex3f (1.0, -1.0, 1.0);
glEnd;
Таблица 1.2. Значение параметра mode
mode | Описание |
GL_POINTS | Каждый вызов glVertex задает отдельную точку. Рисует N точек |
GL_LINES | Каждая пара вершин задает отрезок. Рисует N/2 линий |
GL_LINE_STRIP | Рисуется ломанная. Элементы n и n+1 определяют отрезок n. рисуется N – 1 отрезков |
GL_LINE_LOOP | Рисуется ломанная, причем ее последняя точка соединяется с первой. элементы n и n+1 определяют отрезок n. последняя линия определяется элементом N и 1. рисуется N отрезков |
GL_TRIANGLES | Каждые три вызова glVertex задают треугольник. элементы 3n – 2, 3n‑1, и 3n определяют треугольник n. Рисуется N/3 треугольников. |
GL_TRIANGLE_STRIP | Рисуются треугольники с общей стороной. Для нечетного n, элементы n, n+1, n+2 определяют треугольник n. Для нечетного n элементы n+1, n, n+2 определяют треугольник n. Рисуется N‑1 треугольников. |
GL_TRIANGLE_FAN | Рисует группу соединенных треугольников. Один треугольник определяется для каждого элемента после двух предыдущих. Два последних элемента соединяются с первым. рисуется N – 2 треугольников. |
GL_QUADS | Каждые четыре вызова glVertex задают четырехугольник. рисуется N/4 четырехугольника. |
GL_QUAD_STRIP | Четырехугольники с общей стороной. соединяя чётные элементы с чётными, а нечётные с нечётными. |
GL_POLYGON | Полигон. Элементы с 1 по N определяют этот полигон. (при этом точки полигона сортируются так, чтобы грани у получившегося многоугольника не пересекались) |
Для создания сцены необходимо задать область вывода объектов и задать способ проецирования.
Если область вывода не задана явно, то в OpenGL используется установленная по умолчанию зона в виде куба видимости 2x2x2 с началом координат в центре куба (рис. 2).
Рис. 2. Вид системы координат Oxyz
Система координат в OpenGL Oxyz (рис. 2) расположена таким образом, что ось Oz направлена в сторону противоположную направления зрения. Окно видимости (Windows) масштабируется в пределах [-1; 1] по осям Ox, Oy. Изображение по умолчанию воспроизводится на плоскости z=0.
Существует два типа проецирования: параллельная проекция и перспективная. Ортогональная проекция – это частный случай параллельной проекции, при которой проецирующие лучи ортогональны картинной плоскости.
При ортогональном проецировании точка (x, y, z) на объекте проецируется в точку (x, y, 0) на плоскости проекции. В OpenGL ортогональная проекция, характеризуемая параллелепипедом видимости, задаётся функцией glOrtho(), объявленной следующим образом:
glOrtho (left, right, bottom, top, near, far)
Таким образом, видны все объекты, которые попали внутрь параллелепипеда видимости.
При проецировании, преобразование координат включает в себя этапы, изображённые на рис. 3. Сначала мировые координаты (система координат, в которой определяется положение объекта, положение точки наблюдения и экрана) преобразовываются в видовые координаты. При этом точки изображения остаются на своих местах, но система мировых координат переходит в систему видовых координат. Затем выполняется перспективное преобразование, добавляющее эффект перспективы в зависимости от расстояния от объекта до экрана и расстояние от точки наблюдения до экрана. Система трёхмерных видовых координат переходит в систему двухмерных экранных координат. При построении параллельной проекции перспективное преобразование не выполняется, и видовые координаты используются в качестве экранных координат (X, Y).
1.5 Видовые преобразования
Видовые преобразования осуществляются с помощью матричных преобразований. В OpenGL текущая матрица преобразований является произведением двух матриц – матрицы модели и матрицы проецирования, при этом формируется единая матрица преобразования, которая применяется ко всем вершинам всех геометрических объектов.
Матрица модели – glMatrixMode (GL_MODELVIEW) связана с координатами объектов. Это матрица в базисе видовых координат, она используется для построения картинки в том виде как её видит наблюдатель.
Матрица проецирования – glMatrixMode (GL_PROJECTION). Матрица в системе координат устройства. Вычисляет нормализованные координаты, которые преобразуются в экранные после трансформаций, связанных с областью вывода.