Руководство по работе с графической библиотекой OpenGL. Руководство разработано с учетом опыта чтения курса Компьютерная графика
Скачать 0.66 Mb.
|
36 Глава 2. Введение в OPENGL Все вызовы команд OpenGL происходят в обработчиках событий. Более подробно они будут рассмотрены в следующих главах. Сейчас обратим внимание на функцию Display, в которой сосредоточен код, непосредственно отвечающий за рисование на экране. Следующая последовательность команд из функции Display(): glClearColor (0, 0, 0, 1); glClear (GL_COLOR_BUFFER_BrT); glColor3ub (255 ,0 ,0); glBegin(GL_QUADS); glVertex2f (left , bottom ) ; glVertex2f (left , top ); glVertex2f( right , top ); glVertex2f( right , bottom ) ; glEnd(); очищает окно и выводит на экран квадрат, задавая координаты четырех угловых вершин и цвет. В приложении Б приведен еще один пример несложной программы, при нажатии кнопку мыши рисующей на экране разноцветные случайные прямоугольники. 2.6. Контрольные вопросы В чем, по вашему мнению, заключается необходимость создания стандартной графической библиотеки? Кратко опишите архитектуру библиотек OpenGL и организацию конвейера. В чем заключаются функции библиотек, подобных GLUT или GLX? Почему они формально не входят в OpenGL? Назовите категории команд (функций) библиотеки. 2.6. Контрольные вопросы 37 Почему организацию OpenGL часто сравнивают с конечным автоматом? Зачем нужны различные варианты команд OpenGL, отличающиеся только типами параметров? 7) Что можно сказать о количестве и типе параметров команды glColor4ub()? glVertex3fv()? Глава 3. Рисование геометрических объектов 3.1. Процесс обновления изображения Как правило, задачей программы, использующей OpcnGL, является обработка трехмерной сцены и интерактивное отображение в буфере кадра. Сцена состоит из набора трехмерных объектов, источников света и виртуальной камеры, определяющей текущее положение наблюдателя. Обычно приложение OpenGL в бесконечном цикле вызывает функцию обновления изображения в окне. В этой функции и сосредоточены вызовы основных команд OpenGL. Если используется библиотека GLUT, то это будет функция с обратным вызовом, зарегистрированная с помощью вызова glutDisplayFuncQ. GLUT вызывает эту функцию, когда операционная система информирует приложение о том, что содержимое окна необходимо перерисовать (например, если окно было перекрыто другим). Создаваемое изображение может быть как статичным, так и анимированным, т.е. зависеть от каких-либо параметров, изменяющихся со временем. В этом случае лучше вызывать функ- 39 40 Глава 3. Рисование геометрических объектов цию обновления самостоятельно. Например, с помощью команды glutPostRedisplay(). За более подробной информацией можно обратиться к главе 10. Приступим, наконец, к тому, чем занимается типичная функция обновления изображения. Как правило, она состоит из трех шагов: очистка буферов OpenGL; установка положения наблюдателя; преобразование и рисование геометрических объектов. Очистка буферов производится с помощью команды: void glClearColor ( clampf r, clampf g, clampf b, clampf a ) void glClear ( bitfield buf) Команда glClearColor устанавливает цвет, которым будет заполнен буфер кадра. Первые три параметра команды задают R,G и В компоненты цвета и должны принадлежать отрезку [0,1]. Четвертый параметр задает так называемую альфа компоненту (см. п. 7.1). Как правило, он равен 1. По умолчанию цвет —черный (0,0,0,1). Команда glClear очищает буферы, а параметр buf определяет комбинацию констант, соответствующую буферам, которые нужно очистить (см. главу 7). Типичная программа вызывает команду glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_B]T) для очистки буферов цвета и глубины. Установка положения наблюдателя и преобразования трехмерных объектов (поворот, сдвиг и т.д.) контролируются с помощью задания матриц преобразования. Преобразования объектов и настройка положения виртуальной камеры описаны в главе 4. 3.2. Вершины и примитивы 41 Сейчас сосредоточимся на том, как передать в OpenGL описания объектов, находящихся в сцене. Каждый объект является набором примитивов OpenGL. 3.2. Вершины и примитивы В OpenGL вершина (vertex) является атомарным графическим примитивом и определяет точку, конец отрезка, угол многоугольника и т.д. Все остальные примитивы формируются с помощью задания вершин, входящих в данный примитив. Например, отрезок определяется двумя вершинами, являющимися концами отрезка. С каждой вершиной ассоциируются ее атрибуты. В число основных атрибутов входят положение вершины в пространстве, цвет вершины и вектор нормали. 3.2.1. Положение вершины в пространстве Положение вершины определяются заданием ее координат в двух-, трех-, или четырехмерном пространстве (однородные координаты). Это реализуется с помощью нескольких вариантов команды glVertex: void glVertex[2 3 4][s i f d] (type coords) void glVertex[2 3 4][s i f d]v (type *coords) Каждая команда задает четыре координаты вершины: х, у, z, w. Команда glVertex2* получает значения х и у. Координата z в таком случае устанавливается по умолчанию равной 0, координата w — равной 1. glVertex3* получает координаты х, у, z и заносит в координату w значение 1. glVertex4* позволяет задать все четыре координаты. Для ассоциации с вершинами цветов, нормалей и текстурных координат используются текущие значения соответствующих данных, что отвечает организации OpenGL как конечного 42 Глава 3. Рисование геометрических объектов автомата. Эти значения могут быть изменены в любой момент с помощью вызова соответствующих команд. 3.2.2. Цвет вершины Для задания текущего цвета вершины используются команды void glColor[3 4][b s i f] (GLtype components) void glColor[3 4][b s i f]v (GLtype components) Первые три параметра задают R, G, В компоненты цвета, а последний параметр определяет коэффициент непрозрачности (так называемая альфа-компонента). Если в названии команды указан тип «f» (float), то значения всех параметров должны принадлежать отрезку [0,1], при этом по умолчанию значение альфа-компоненты устанавливается равным 1.0, что соответствует полной непрозрачности. Тип «ub» (unsigned byte) подразумевает, что значения должны лежать в отрезке [0,255]. Вершинам можно назначать различные цвета, и, если включен соответствующий режим, то будет проводиться линейная интерполяция цветов по поверхности примитива. Для управления режимом интерполяции используется команда void glShadeModel (GLenum mode) вызов которой с параметром GL_SMOOTH включает интерполяцию (установка по умолчанию), а с GL_FLAT — отключает. 3.2.3. Нормаль Определить нормаль в вершине можно, используя команды void glNormal3[b s i f d] (type coords) void glNorma!3[b s i f d]v (type coords) 3.3. Операторные скобки GLBEGIN / GLEND 43 Для правильного расчета освещения необходимо, чтобы вектор нормали имел единичную длину. В OpenGL существует специальный режим, при котором задаваемые нормали будут нормироваться автоматически. Его можно включить командой glEnable(GL_NORMALIZE). Режим автоматической нормализации должен быть включен, если приложение использует модельные преобразования растяжения/сжатия, так как в этом случае длина нормалей изменяется при умножении на модельно-видовую матрицу. Однако применение этого режима уменьшает скорость работы механизма визуализации OpenGL, так как нормализация векторов имеет заметную вычислительную сложность (взятие квадратного корня). Поэтому лучше сразу задавать единичные нормали. Отмстим, что команды void glEnable (GLenum mode) void glDisable (GLenum mode) производят включение и отключение того или иного режима работы конвейера OpenGL. Эти команды применяются достаточно часто, и их возможные параметры будут рассматриваться в каждом конкретном случае. 3.3. Операторные скобки glBegin / glEnd Мы рассмотрели задание атрибутов одной вершины. Однако чтобы задать атрибуты графического примитива, одних координат вершин недостаточно. Эти вершины надо объединить в одно целое, определив необходимые свойства. Для этого в OpenGL используются так называемые операторные скобки, являющиеся вызовами специальных команд OpenGL. Определение примитива или последовательности примитивов происходит между вызовами команд 44 Глава 3. Рисование геометрических объектов void glBegin (GLenum mode) void glEnd (void) Параметр mode определяет тип примитива, который задается внутри и может принимать следующие значения: GL POINTS —каждая вершина задает координаты некоторой точки. GL LINES —каждая отдельная пара вершин определяет отрезок; если задано нечетное число вершин, то последняя вершина игнорируется. GL LINE STRIP — каждая следующая вершина задает отрезок вместе с предыдущей. GL LINE LOOP —отличие от предыдущего примитива только в том, что последний отрезок определяется последней и первой вершиной, образуя замкнутую ломаную. GL TRIANGLES — каждые отдельные три вершины определяют треугольник; если задано не кратное трем число вершин, то последние вершины игнорируются. |