3 С. А. Васильев opengl компьютерная графика
Скачать 491.09 Kb.
|
Ошибка! Продолжение табл. Значение mode Описание 0 3 2 4 1 11 Значение mode Описание GL_LINES ФОРМИРУЕТ ОТРЕЗКИ (ОТ- РЕЗОК) ПРЯМЫХ. КАЖДАЯ ПОСЛЕДОВАТЕЛЬНАЯ ПАРА ВЕРШИН ОПРЕДЕЛЯЕТ ОТ- РЕЗОК; ЕСЛИ ЗАДАНО НЕ- ЧЕТНОЕ ЧИСЛО ВЕРШИН, ТО ПОСЛЕДНЯЯ ВЕРШИНА ИГНОРИРУЕТСЯ. ПЕРВЫЕ ДВЕ ВЕРШИНЫ ЗАДАЮТ ПЕРВЫЙ ОТРЕЗОК, СЛЕ- ДУЮЩИЕ ДВЕ – ВТОРОЙ И Т.Д. GL_LINE_STRIP Задается ломаная. Каждая сле- дующая вершина является концом текущего отрезка прямой и началом для следую- щего. Ошибка! GL_LINE_LOOP Задается замкнутая ломаная. В от- личие от предыдущего примитива (GL_LINE_STRIP) последний отре- зок определяется послед-ней и первой вершиной. Продолжение табл. Значение mode Описание GL_TRIANGLES Задаются треугольники (треуголь- ник). Каждые три вершины, сле- 0 1 2 3 4 5 0 1 3 2 0 1 2 3 0 3 12 Значение mode Описание дующие друг за другом, опреде- ляют отдельный треугольник. Ес- ли количество вершин не кратно трем, то "лишние" вершины игно- рируются. GL_TRIANGLE_STRI P Задается полоса из связанных тре- угольников, имеющих общую грань. Каждая вер-шина, начиная с третьей, вместе с двумя предыду- щими задает треугольник. Следо- вательно первый треугольник – v0, v1, v2; второй – v1, v3, v2; третий – v2, v3, v4 и т.д. Отрезки v1-v2, v2- v3, v3-v4 и т.д. являются общими гранями треугольников. Ошибка! GL_TRIANGLE_FAN Задается "веер" связанных тре- угольников, имеющих общую вершину – первую вершину (v0). Тогда первый треугольник – v0, v1, v2; второй – v0, v2, v3; третий – v0, v3, v4 и т.д. Отрезки v0-v2, v0- v3, v0-v4 и т.д. являются общими гранями треугольников. Ошибка! Окончание табл. Значение mode Описание GL_QUADS Задает четырехугольник. Каждая последовательная четверка вер- шин определяет четырехугольник. Если количество вершин не крат- но четырем, то "лишние" вершины 0 1 2 3 4 5 0 1 3 5 2 4 13 Значение mode Описание игнорируются. Ошибка! GL_QUAD_STRIP Задает полосу из связанных четы- рехугольников. Каждые два со- седних четырехугольника имеют одно общее ребро. Первый четы- рехугольник – v0, v1, v3, v2; вто- рой – v2, v3, v5, v4; третий – v4, v5, v7, v6 и т.д. Отрезки v2-v3, v4-v5 и т.д. являются общими гранями со- седних четырехугольников. GL_POLYGON Задается выпуклый многоуголь- ник. Последняя вершина автома- тически соединяется с первой. Например, чтобы отобразить один четырехугольник с разными цветами в вершинах, достаточно реализовать следующий фрагмент кода: GLfloat Green[3] = {0.0, 1.0, 0.0}; glBegin(GL_QUADS); glColor3f (1.0, 0.0, 0.0); // Красный glVertex3f(0.0, 0.0, 0.0); glColor3f (1.0, 1.0, 1.0); // Белый glVertex3f(1.0, 0.0, 0.0); glColor3fv(Green); // Зеленый glVertex3f(1.0, 1.0, 0.0); glColor3f (0.0, 0.0, 1.0); // Синий glVertex3f(1.0, 1.0, 1.0); glEnd(); В связи с тем, что на практике очень часто приходится рисовать прямоугольники, то в OpenGL включили команду рисования такого примитива: void glRect[sifd] (type x1, type y1, type x2, type y2) void glRect[sifd]v (const type *v1, const type *v2) 0 1 2 3 4 0 1 3 2 5 4 7 6 0 1 2 3 4 5 6 7 14 Эта команда рисует прямоугольник в плоскости z = 0. Левый нижний угол прямоугольника опреде- ляется параметрами (x1, y1), а противоположный (по диагонали) (x2, y2). В случае векторной формы ко- манды, углы задаются в виде двух указателей на массивы, каждый из которых содержит значения (x, y). При визуализации многоугольников следует различать лицевую грань и нелицевую (обратную). Если при рассмотрении многоугольника его список вершин обходится по часовой стрелке, то такая грань многоугольника лицевая. Если против часовой, то – нелицевая. В OpenGL существует механизм управления растеризацией многоугольников на экране. Для этого используется команда void glPolygonMode (GLenum face, Glenum mode) Параметр mode определяет, как будут отображаться многоугольники, а параметр face устанавлива- ет тип многоугольников, к которым будет применяться эта команда и может принимать следующие значения: face Вид грани GL_FRONT Лицевые GL_BACK Нелицевые GL_FRONT_AND_BAC K Лицевые и нелицевые mode Вид отображения грани GL_POI NT Отображение только отдельных вершин много- угольников. GL_LINE Отображение многоугольников в виде набора отрезков. GL_FILL Многоугольники будут закрашиваться текущим цветом (режим установлен по умолчанию). Для каждой вершины геометрического объекта можно задать свой вектор нормали следующей ко- мандой: void glNormal3[b s i f d] ( type nx, type ny, type nz) void glNormal3[b s i f d] v (const type *n) Для включения автоматического приведения векторов к единичным применяют команду: glE- nable(GL_NORMALIZE). 5.3 Управление размерами точки По умолчанию, размер точки, толщина линии в примитивах соответствует одному пикселю на эк- ране, линия всегда непрерывная. Но эти параметры в OpenGL можно изменять. Рассмотрим некоторые команды предназначенные для этой цели. Размер точки можно легко изменить командой – void glPointSize(GLfloat size), где параметр size за- дает размер "квадрата" точки в пикселях. Дело в том, что при большом увеличении точки можно уви- деть ее квадратность. Если данный параметр имеет значение 2, то точка будет выглядеть как квадрат 2 ×2. Для сглаживания углов "квадрата" точки больших размеров используется команда glEnable(GL_POINT_SMOOTH), которая включает антиалиасинг точки. Выключение антиалиасинга для точки осуществляется командой glDisable с параметром (GL_POINT_SMOOTH). По умолчанию анти- алиасинг выключен. Вот как выглядит фрагмент программы рисования "круглой" точки размеров 3 пикселя: glEnable(GL_POINTS); // Будем работать с точкой glEnable(GL_POINT_SMOOTH); // Разрешаем антиалиасинг точки glPointSize(3.0); // Задаем размер точки glBegin(GL_POINTS); // Определяем координаты рисования glVertex2i(100,100); glEnd(); 15 glDisable(GL_POINT_SMOOTH); // Запрещает антиалиасинг точки 5.4 Управление толщиной и шаблоном линии По умолчанию, толщина линии в примитивах соответствует одному пикселю на экране, линия все- гда непрерывная. Эти параметры в OpenGL можно изменять. Рассмотрим некоторые команды предна- значенные для этой цели. Толщина линии задается командой void glLineWidth (GLfloat width) Параметр width задает в пикселях толщину линии и должен быть больше (0.0f). Как и в случае с точкой, мы можем включать или выключать сглаживание линии командами glE- nable/glDisable с параметром GL_LINE_SMOOTH. Внимание! Если не включать сглаживание линии, а этот режим является базовым по умолчанию, то толщина линии будет визуально изменяться в зависи- мости от угла наклона. Дело в том, что в этом режиме толщина линии определяется вдоль оси y, если |y 1 – y 2 | < |x 1 – x 2 | (где (x 1 , y 1 ) и (x 2 , y 2 ) – координаты концов отрезка) и в направлении оси x в ситуации |y 1 – y 2 | > |x 1 – x 2 |. А в случае сглаживания толщина линии замеряется перпендикулярно линии. Если требуется рисовать линию фрагментарно, т.е. не непрерывно, то для это цели используют шаблоны. Шаблон линии задается командой: void glLineStipple (Glint factor, GLushort pattern) Параметр pattern – это и есть шаблон 16-точечного фрагмента линии, который состоит из серии ну- лей и единиц. Единица означает, что соответствующая точка линии будет нарисована на экране, ноль означает, что точка нарисована не будет. Запись шаблона начинается с младшего бита параметра pattern. Например, шаблон вида 0x00FF запретит выводить первые восемь точек отреза линии, после чего будет разрешено выводить восемь точек, и так до конца линии. К шаблону можно применит мас- штабирование (в сторону увеличения), это определяется параметром factor. Если factor равен 2, то каж- дый бит шаблона при наложении на отрезок будет представлен двумя точками идущих друг за другом. Например, если в шаблоне встречаются подряд две единицы, а затем три нуля и factor равен 2, то шаблон этот фрагмент рассматриваться как содержащий 4 единицы и 6 нулей. Максимальное увеличение шаб- лона ограничено числом 256. Использование команды glLineStipple() должно быть разрешено командой glEnable()с параметром GL_LINE_STIPPLE. Команда glDisable() с этим же параметром запрещает ра- боту с шаблоном. Рассмотрим пример построения линии состоящей из повторяющихся точек через одну. Для этого потребуется шаблон 0xAAAA: glLineStipple(1,0xAAAA); // Задаем шаблон с масштабом 1 glEnable(GL_LINE_STIPPLE); // Разрешаем работу шаблоном glEnable(GL_LINES); glBegin(GL_LINES); glColor3f(1.0f,1.0f,0.0f); glVertex2i(40,120); glVertex2i(240,120); glEnd(); glDisable(GL_LINES); glDisable(GL_LINES_STIPPLE); // Запрещаем работу с шаблоном Если в приведенном примере в команде glLineStipple(1,0xAAAA) заменить масштабный множитель шаблона 1 на значение 20 (glLineStipple(20,0xAAAA)), то на экране вместо точек увидим отрезки пря- мых длиной в 20 пиксель. 5.5 Грани плоских многоугольников Каждый плоский многоугольник имеет две стороны – лицевую и обратную. Если посмотреть на по- верхность многоугольника и описать его списком вершин обходя многоугольник против хода часовой стрелки, то такая грань называется лицевая. В противном случае – обратная. Очевидно, что лишь одна грань многоугольника может быть видна. Чтобы не делать лишней работы на невидимых гранях объек- та необходимо эту ситуацию отслеживать. По умолчанию в OpenGL считается, что многоугольник зада- ется вершинами против часовой стрелки. Но это правило можно изменить командой void glFrontFace (GLenum mode) Значением параметра mode можно изменять правило задания вершин для лицевых граней. Если этот 16 параметр принимает значение символьной константы GL_CW то признак лицевой грани – обход вер- шин по часовой стрелке и GL_CCW – против часовой стрелки. Лицевые или обратные грани можно целенаправленно исключать из процесса вывода полигонов. Рассмотрим команду осуществляющую управление выводом полигонов в зависимости от типа грани: void glCullFace (GLenum mode) Если значение параметра mode равно GL_FRONT, то не будут отображаться лицевые грани. Также возможны значения GL_BACK и GL_FRONT_AND_BACK. По умолчанию берется значение GL_BACK, т.е. выводить только лицевые грани. Перед тем как использо- вать glCullFace()необходимо выполнить команду glEnable(GL_CULL_FACE), которая разрешит ис- пользовать данный режим. Блокировка данного режима осуществляется командой glDisable(GL_CULL_FACE). Рассмотрим небольшой пример работы с лицевыми и обратными гранями полигонов: … glEnable(GL_CULL_FACE); // Вкл. режим упр. выводом граней //glCullFace(GL_FRONT); // Исключить вывод лицевых граней glColor3f(1.0f, 0.0f, 0.0f);//Красный цвет для треугольника glBegin(GL_TRIANGLES); // Треугольник (против часовой) glVertex3i( 100, 100, 0); // Вершина 1 glVertex3i( 50, 50, 0); // Вершина 2 glVertex3i( 150, 50, 0); // Вершина 3 glEnd(); glColor3f(0.0f, 1.0f, 0.0f); //Зеленый цвет для прямоугольника glBegin(GL_QUADS); // Прямоугольник (по часовой) glVertex3i(200, 100, 0); // Вершина 1 glVertex3i(250, 100, 0); // Вершина 2 glVertex3i(250, 50, 0); // Вершина 3 glVertex3i(200, 50, 0); // Вершина 4 glEnd(); … Если посмотреть на результат работы данного фрагмента программы, то можем увидеть на экране только красный треугольник, так как зеленый прямоугольник был отброшен (по умолчанию в данном режиме отбрасываются обратные грани полигонов). Если разблокировать команду glCull- Face(GL_FRONT)(убрать комментарии), то на экране вместо треугольника появится прямоугольник зе- леного цвета. Его описание соответствует нелицевой грани. 5.6 Заполнение полигонов шаблонами По умолчанию полигоны заполняются без рисунка – однородным значением. Для заполнения поли- гона повторяющимся орнаментом используют команду, использующую битовую карту: void glPolygonStipple (const GLubyte *mask) Предварительно готовится битовая карта размером 32 ×32 бит, являющаяся маской, циклично (по мере необходимости) накладываемой на полигон при его выводе в растр. Там, где стоит 1 – соответст- вующий пиксель полигона будет нарисован, а там, где появляется 0 – пиксель нарисован не будет. Па- раметр mask – это указатель на массив битовой карты. Покрытие шаблоном полигона разрешается и за- прещается с помощью команд glEnable() и glDisable()с параметром GL_POLYGON_STIPPLE. Варьи- руя параметрами GL_UNPACK* команды glPixelStore*()можно изменять режим хранения пикселей в памяти(смотри MSDN), что повлечет за собой видоизменение внутреннего рисунка в полигоне. Рассмотрим пример использования шаблона для заполнения четырехугольного полигона. Первые четыре байта (0 ×ff,0×ff,0×ff,0×ff) массива Bit_Map описывают нижнюю строчку трафарета, вторая чет- верка (0x01,0x01,0x01,0x01) – вторую снизу строчку трафарета и т.д. Более наглядней оформлять лис- тинг шаблона в программе матрицей размером 4x32, но для экономии места приходится 16x16, т.е. две строки шаблона записывать в одной строке листинга. GLvoid DrawPrim() { // Формируем шаблон полигона 32x32 бит!!! 17 GLubyte Bit_Map[]= { 0xff,0xff,0xff,0xff,0x01,0x01,0x01,0x01, 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01, … (для экономии места - пропущены шесть одинаковых наборов) 0xff,0xff,0xff,0xff,0x01,0x01,0x01,0x01, 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01 }; glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0,1.0,1.0); //Задаем белый цвет glEnable(GL_POLYGON_STIPPLE); //Включаем шаблон glPolygonStipple(Bit_Map); //Определяем шаблон glBegin(GL_POLYGON); //Рисуем полигон glVertex2i(10, 10); glVertex2i(30, 60); glVertex2i(100, 70); glVertex2i(80, 20); glEnd( ); glDisable(GL_POLYGON_STIPPLE); //Выключаем шаблон } 5.7 Воспроизведение битовых массивов В OpenGL имеется возможность рисовать растровые изображения на основании одномерного би- тового массива. Там, где стоит 1 – пиксель будет нарисован, а там, где появляется 0 – пиксель нарисо- ван не будет. Битовый массив при выводе разбивается на строки, которые, в свою очередь, набираются в высоту изображения. Для этого используется команда void glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) Параметры width и height задают в пикселях ширину и высоту точечного рисунка, представленного в виде битового массива, xorig и yorig уточняютадрес левого нижнего угла точечного изображения в плоскости экрана по формулам x окн = x тек – xorig и y окн = y тек – yxorig, где x окн и y окн оконные координаты; x тек и y тек текущие координаты растровой позиции, задаваемые командойglRasterPos*(). Параметры xmov и ymov показывают на сколько изменится текущая позиция растра после вывода битового изобра- жения. Переменная bitmap указывает на адрес в оперативной памяти компьютера, начиная с которого хранится битовый образ. Перед тем, как рассмотреть несколько примеров использования команды glBitmap() необходимо разобраться как в OpenGL задаются координаты текущей точки растра. Для установки оконных коорди- нат используется команда void glRasterPos[234][s I f d](GLtype coords) void glRasterPos[234][s I f d]v(GLtype coords) где cords – координаты текущей позиции растра. По умолчанию текущая позиция растра установлена по координатам (0, 0, 0, 1). Кроме этого, для успешной работы с командой glBitmap() требуется устанавливать режим хранения пиксель в памяти. А это нам обеспечит команда void glPixelStore[f i](GLenum pname, GLtype param) Параметр pname задает символьную константу, указывающую на определенный устанавливаемый параметр, а param – конкретное значение для данного параметра. Рассмотрим возможные символьные константы для параметра pname: Pname Значение param 18 Pname Значение param GL_PACK_SWAP_BYTES, GL_UNPACK_SWAP_BYT ES • ЕСЛИ TRUE, ТО БАЙТЫ В МНОГОБАЙТНЫХ КОМПОНЕНТАХ ЦВЕТА, ГЛУБИНЫ И ИНДЕКСА ТРАФАРЕТА УПОРЯДО- ЧЕНЫ В ОБРАТНОМ ПО- РЯДКЕ GL_PACK_LSB_FIRST, GL_UNPACK_LSB_FIRST • Если TRUE, то биты внутри байта упорядочены от млад- ших разрядов к старшим GL_PACK_ROW_LENGT H, GL_UNPACK_ROW_LEN GTH • param определяет число пикселей в строке GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS, GL_UNPACK_SKIP_PIXE LS, GL_UNPACK_SKIP_ROW S • Значением param можно за- давать количество пропускае- мых пиксель или строк GL_PACK_ALIGNMENT, GL_UNPACK_ALIGNMEN T • Выравнивание начала стро- ки пикселей в памяти: 1 – по байту; 2 – по четному байту; 4 – по слову; 8 – по двойному слову. По умолчанию – 4 (по слову) Теперь мы можем рассмотреть пример работы команды glRasterPos*(). Пусть требуется вывести на экран в точке с координатами (100, 50) символ Т. Образ его и соответствующие кодировочные числа приведены на рисунке 1. Рассмотрим эту задачу по шагам. |