Е. А. Снижко, Н. А. Флерова
Скачать 0.57 Mb.
|
Контрольные вопросы 1. Что понимается под контекстом устройства? 2. Что представляет собой контекст воспроизведения? 3. Какие основные фрагменты должна содержать минималь- ная программа OpenGL. 4. Что входит в понятие формат пикселя? 5. Какие библиотечные файлы должны быть подключены к программе для работы с OpenGL? 6. Какая цветовая модель используется при определении цвета в данной программе? 7. Какие параметры следует указать, чтобы цвет фона был зеленым? 8. Для чего нужна функция масштабирования сцены? 9. В какой секции кода можно записывать команды рисова- ния сцены? 10. Какое правило необходимо соблюдать, чтобы иметь воз- можность перехода в полноэкранный режим? 17 Лабораторная работа № 2 ПРИМИТИВЫ OPENGL, ОСНОВНЫЕ ПРИЕМЫ ПОСТРОЕНИЯ ДВУМЕРНЫХ ОБЪЕКТОВ Цель работы – знакомство с примитивами OpenGL, предна- значенными для вывода точек, линий и многоугольников; опре- деление цвета объектов, различные способы закрашивания объ- ектов. Необходимые теоретические сведения Для выполнения работы необходимо иметь представление об основных принципах формирования изображения на экране (лекция 17), о моделировании объектов на плоскости (лекции 7, 8, 10); знать особенности представления цвета в цветовой модели RGB (лекция 4); понимать смысл термина «антиэлайзинг» (лекция 6) [7]. Область вывода в OpenGL задается командой glViewPort(0, 0, ClientWidth, ClientHeight), где первые два параметра определяют положение левого верхне- го угла окна вывода, параметры ClientWidth, ClientHeight – раз- мер окна в экранных координатах. Центр полученной области вывода имеет координаты (0, 0), которые изменяются в диапазоне [-1; 1] по каждой оси. Если при установке формата пикселя был установлен режим двойной буферизации (флаг PFD_DOUBLEBUFFER), то изобра- жение готовится во внеэкранном буфере и необходимо обеспе- чить перезапись содержимого внеэкранного буфера в основной. Сделать это можно командой BOOL SwapBuffers(HDC hdc); Все изображения строятся из отдельных примитивов, кото- рые описываются с помощью набора вершин (Vertex). Примити- вами OpenGl являются точки (одиночные вершины), линии (пары вершин), треугольники (три вершины), четырехугольники (четы- ре вершины) и полигоны (три и более вершин). 18 Командные скобки. Использование функций glBegin и glEnd. Команды рисования заключаются между командными скобками glBegin и glEnd. Командные скобки библиотеки OpenGl представляют собой специальные функции, не имеющие никако- го отношения к операторным скобкам языков программирования. Ошибка при использовании командных скобок не распознается компилятором, но может привести к непредсказуемым результа- там работы программы. Внутри командных скобок могут находиться любые операто- ры языка и многие функции OpenGL. Главное назначение ко- мандных скобок – задание режима (примитива) для команд glVer- tex (вершина), определяющих координаты вершин для рисования примитивов OpenGL. Команды, устанавливающие размер точки, толщину и тип линии, включение и отключение режима сглаживания (антиэлай- зинг), должны стоять вне командных скобок. Цвет отдельных вершин или примитивов может устанавли- ваться как вне командных скобок, так и внутри них. Для уста- новки цвета используется команда glColor3f(0.3f, 0.5f, 0.1f), где цвет формируется как сумма компонентов красного, зеленого и синего цветов в указанной пропорции. Значения компонентов задаются в виде вещественных чисел в интервале [0; 1]. Компоненты цвета могут быть заданы и в целочисленной форме. Предельным значением в этом случае будет являться мак- симальное 8-битное целое без знака; например, белый цвет будет записан следующим образом: glColor3i(214748647, 214748647, 214748647). Однако предпочтительно использовать команду в вещест- венной форме, так как OpenGL хранит данные именно в вещест- венном формате. Цифра 3 в названии команды означает число аргументов ко- манды. Аргументы функции glBegin. Аргументами функции glBegin могут быть стандартные константы OpenGl, определяющие при- 19 митивы библиотеки: GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, GL_POLYGON. В программе имена констант должны быть записаны именно так как это сделано здесь (все в верхнем реги- стре). Включение и отключение режима сглаживания (анти- элайзинг). Для установки режима сглаживания перед командны- ми скобками должна стоять команда glEnable() с соответствую- щей константой в качестве аргумента, а после командных скобок – команда glDisable() также с соответствующей константой. Вы- бор константы определяется примитивом, сглаживание которого должно быть включено (или отключено): GL_POINT_SMOOTH (сглаживание для точек), GL_LINE_SMOOTH (сглаживание ли- ний), GL_POLYGON_SMOOTH (сглаживание для полигонов). Вывод точек в OpenGL. Рассмотрим рисование точек. Точки представляют собой одиночные вершины. Для рисования верши- ны используется команда glVertex. Если точка должна быть изо- бражена на плоскости, то для определения ее положения необхо- димы две координаты. В этом случае используется функция с двумя аргументами: glVertex2f(0, 0). Буква f в названии функции определяет тип аргументов – вещественные числа (float). Точка в пространстве определяется тремя координатами, следовательно, должна использоваться команда с тремя аргументами: glVertex3f(0.5, 0.3,-0.7). Команды glVertex должны размещаться между командными скобками. При этом число точек может быть любым. Аргументом функции glBegin для рисования точек является константа GL_POINTS. Аргументом команд glEnable() и glDisable() для включе- ния/отключения режима сглаживания является константа GL_POINT_SMOOTH. Для задания размера точки используется команда glPointSize(). Аргументом является натуральное число, определяющее размер точки в пикселях. В режиме сглаживания существует ограничение на размер точек. Определите экспери- ментально максимальный размер точки, выводимой в режиме сглаживания. 20 П р и м е р: glColor3f(1.0, 0.0, 0.0); // Установили красный цвет glEnable(GL_POINT_SMOOTH); // Включение режима // сглаживания для точек glPointSize(3); // Установили размер точки 3 пикселя glBegin(GL_POINTS); // Режим рисования - точки glVertex2f(-0.5, -0.7); glVertex2f(0.0, 0.0); glVertex2f(0.1, 0.9); glVertex2f(0.3, -0.5); glEnd(); // Конец рисования glDisable(GL_POINT_SMOOTH); // Отключение режима // сглаживания для точек Линии: одиночные, ломаные, замкнутые ломаные. Для ри- сования линий существует три режима: одиночные линии, лома- ная, замкнутая ломаная. Одиночная линия определяется двумя вершинами. Если тре- буется нарисовать несколько одиночных линий, то между ко- мандными скобками должны быть описаны координаты пар вер- шин, т.е. число команд glVertex между командными скобками должно быть четным. Если число вершин нечетно, последняя вершина игнорируется. Аргументом функции glBegin для рисования одиночных ли- ний является константа GL_LINES. Аргументом команд glEnable() и glDisable() для включе- ния/отключения режима сглаживания является константа GL_LINE_SMOOTH. Для задания толщины линии используется команда glLineWidth(). Аргументом является натуральное число, опреде- ляющее толщину в пикселях. Так же как и при установке размера точки, команду установки толщины линии записывают за преде- лами командных скобок. Для изменения типа линии используется команда glLineStip- ple(), имеющая два аргумента. Первый аргумент – масштабный множитель, а второй представляет собой 16-ю константу 4 , опре- деляющую шаблон штриховки (побитовым способом). Эта ко- манда должна стоять вне операторных скобок. 4 В Delphi шаблон запишется в виде, например, $ F0F0. 21 П р и м е р. glColor3f(1.0, 0.0, 0.0); // Установили красный цвет glEnable(GL_LINE_SMOOTH); // Включение режима // сглаживания для линий glLineWidth(3); // Установили толщину линии 3 пикселя glLineStipple(1, 0xF0F0); // Тип линии – пунктирная glEnable(GL_LINE_STIPPLE); // Разрешить изменение // типа линии glBegin(GL_LINES); // Режим рисования – одиночные линии glVertex2f(-0.5, -0.7); // Начало первой линии glVertex2f(0.0, 0.0); // Конец первой линии glVertex2f(0.1, 0.9); // Начало второй линии glVertex2f(0.3, -0.5); // Конец второй линии glEnd(); // Конец рисования glDisable(GL_LINE_SMOOTH); // Отключение режима // сглаживания для линий Если требуется нарисовать ломаную линию, то в командных скобках используют константу GL_LINE_STRIP. Вершины, пере- численные между командными скобками, интерпретируются сле- дующим образом: конечная точка первой линии является началь- ной точкой следующего звена ломаной и т.д.; число вершин мо- жет быть как четным, так и нечетным. Ширина и тип ломаной линии задаются так же, как и для одиночных линий. Для рисования замкнутой ломаной аргументом функции glBegin должна быть установлена константа GL_LINE_LOOP. Последний отрезок замкнутой ломаной в качестве начала имеет последнюю вершину списка, в качестве конца – первую. Вывод треугольников: одиночные треугольники, ленты треугольников, веера треугольников. Для рисования отдельных треугольников используется константа командных скобок: GL_TRIANGLES. Число вершин, перечисленных между команд- ными скобками, должно быть кратно трем. Каждые три вершины определяют треугольник. Лента треугольников используется, если изображение может быть построено с помощью нескольких треугольников, имеющих смежные стороны (рис. 1). Здесь сторона a2a3 является общей стороной для первого и второго треугольников, сторона a3a4 – общей для второго и третьего треугольников и т.д. Если такую фигуру описывать с 22 помощью одиночных треугольников, то необходимо задавать ко- ординаты всех вершин всех треугольников: a1, a2, a3, a2, a3, a4, a3, a4, a5, a4, a5, a6 – всего 12 вершин. Использование ленты треугольников позволяет не дублировать вершины при описании их координат. Изображенная на рисунке фигура может быть представлена лентой треугольников, координаты вершин пере- числяются в следующем порядке: a1, a2, a3, a4, a5, a6 – доста- точно шести вершин. Константа командных скобок для примитива «лента тре- угольников»: GL_TRIANGLE_STRIP. Другая возможность рисования с помощью треугольников – использование «веера треугольников» в тех случаях, когда не- сколько треугольников имеют общую вершину (рис. 2). При опи- сании вершин первой в списке должна стоять общая вершина. Таким образом, в списке из нескольких вершин первые три опре- деляют первый треугольник, первая, третья и четвертая – второй, первая, четвертая и пятая – третий и т.д. Если в списке имеется N вершин, то будет изображено N-2 треугольника. Константа командных скобок для веера треугольников: GL_TRIANGLE_FAN. Вывод четырехугольников. Константа командных скобок для рисования отдельных четырехугольников: GL_QUADS. Четырехугольник определяется группой из четырех вершин, следовательно, число вершин, записанных между командными скобками, должно быть кратно четырем. Лишние вершины игно- рируются. Каждая четверка вершин определяет отдельный четы- рехугольник. a1 a2 a3 a4 a5 a6 a1 a2 a3 a4 a5 a6 a7 Рис. 1. Лента треугольников Рис. 2. Веер треугольников 23 Если изображение создается из связанных четырехугольни- ков (каждая пара четырехугольников имеет общую сторону), то используется примитив «лента четырехугольников». Константа командных скобок: GL_QUAD_STRIP. Рисование полигонов, передние и задние грани полигонов. Для рисования многоугольников в командных скобках использу- ется константа GL_POLIGON. При этом вершины, указанные ме- жду командными скобками, определяют выпуклый многоуголь- ник. Многоугольник строится из связанных треугольников с об- щей вершиной, в качестве общей вершины берется первая вер- шина списка (см. рис. 2). Список вершин для данного многоугольника: a1, a2, a3, a4, a5, a6, a7. При рисовании многоугольников следует иметь в виду нали- чие лицевых (передних) и обратных (задних) граней. Может воз- никнуть вопрос, зачем при построении плоского изображения различать лицевые и обратные грани? Однако это различение не- обходимо при выводе закрашенных полигонов и тем более при трехмерных построениях. Грань считается лицевой, если вершины перечисляются в на- правлении против часовой стрелки (в положительном направлении для левой системы координат), и обратной, если обход вершин производится по часовой стрелке (в отрицательном направлении). Построение невыпуклых полигонов. Если необходимо изо- бразить невыпуклый многоугольник, то он должен быть пред- ставлен как набор выпуклых многоугольников, каждый из кото- рых описывается в своих командных скобках (рис. 3). a1 a2 a3 a4 a5 a6 a7 Рис. 3. Представление невыпуклого полигона с помощью набора выпуклых полигонов 24 Данную фигуру можно разбить на три выпуклых много- угольника: a1a2a3a4, a1a4a6a7 и a4a5a6. Следовательно, фигура может быть описана как три примитива типа GL_POLIGON. Од- нако заметим, что первая и вторая фигуры – смежные четырех- угольники, а третья – треугольник. Для воспроизведения тре- угольников и четырехугольников желательно использовать «род- ные» примитивы, причем, если это возможно, связанные. То есть для построения изображенной фигуры первые два четырехуголь- ника мы опишем в одних командных скобках как связанные че- тырехугольники с общей стороной a1a4 (последовательность пе- речисления вершин: a2, a3, a4, a1, a7, a6) – используем константу командных скобок GL_QUAD_STRIP. Треугольник a4a5a6 опи- шем в своих командных скобках с константой GL_TRIANGLES. Можно решить эту задачу и другими способами. Вообще, оп- тимальным будет разбиение невыпуклой фигуры на треугольни- ки, поскольку их построение, как правило, реализовано на аппа- ратном уровне. Для сглаживания (антиэлайзинга) многоугольников исполь- зуется константа GL_POLYGON_SMOOTH. Команда использует- ся так же, как для точек и линий. Поскольку треугольники и че- тырехугольники являются многоугольниками, то сглаживание для них осуществляется, как для многоугольников. Особенности режимов закрашивания для многоугольни- ков. До сих пор вы изображали многоугольники с использовани- ем заливки, причем если для разных вершин примитивов были заданы различные цвета, то фигуры окрашивались градиентно, с плавным переходом цветов от вершины к вершине. Это происхо- дит из-за того, что по умолчанию способ тонирования задан плавным. Чтобы изменить его, необходимо перед командными скобками вызвать функцию glShadeModel(GL_FLAT). В этом слу- чае связанные фигуры окрашиваются по правилу старшинства цвета второго примитива. Для задания режима вывода многоугольников (в контурном виде – без заливки, с заливкой) используется команда glPolygon- Mode. Второй параметр команды указывает способ изображения грани фигуры с помощью следующих констант: GL_FILL – вывод граней с заливкой; GL_LINE – каркасный вывод (только конту- ры); GL_POINT – выводятся только вершины. Первый параметр определяет, для каких граней установлен режим: лицевые – 25 GL_FRONT; обратные – GL_BACK; лицевые и обратные – GL_FRONT_AND_BACK. Описанная команда помещается перед командными скобками. Задания к работе Используя программу-шаблон, созданную при выполнении предыдущей лабораторной работы, выполните следующие задания. 1. Построить точки, расположенные в вершинах правильно- го N-угольника. Установить режим сглаживания для точек. Экс- периментально определить максимальный размер точки, при ко- тором возможно сглаживание. 2. Используя примитив для вывода линий, нарисовать пра- вильный N -угольник. Изменить тип и ширину линий. 3. Используя примитив для вывода ломаной линии, нарисо- вать фигуру, изображенную на рис. 1. 4. Используя примитив для вывода замкнутой ломаной, на- рисовать фигуру, изображенную на рис. 2. 5. Построить фигуру, изображенную на рис. 2, разбив ее на треугольники (каждый треугольник окрашен случайным цветом). Выполнить три варианта построений с использованием примитивов: А) треугольник; Б) лента треугольников; В) веер треугольников. Чем различаются результаты при изменении способа тониро- вания? 6. Используя примитив для вывода многоугольников, по- строить правильный N -угольник. 7. Построить невыпуклый многоугольник, изображенный на рис.3, представив его в виде совокупности отдельных много- угольников, назначив каждому из них свой цвет. Посмотреть результат работы программы для различных способов тонирова- ния. 8. Изменить программу предыдущей задачи таким образом, чтобы: А) лицевые грани изображались только вершинами; Б) лицевые грани изображались закрашенными, а обратные – линиями; В) лицевые и обратные грани изображались линиями (кар- касное изображение). 26 Варианты к заданиям (N – числовершин многоугольника) Вариант 1 N=5 Рис. 1 Рис. 2 Рис. 3 Вариант 2 N=7 Рис. 1 Рис. 2 Рис. 3 Вариант 3 N=6 Рис. 1 Рис. 2 Рис. 3 Вариант 4 N=4 Рис. 1 Рис. 2 Рис. 3 Вариант 5 N=8 Рис. 1 Рис. 2 Рис. 3 |