Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

RedBook

.pdf
Скачиваний:
18
Добавлен:
11.06.2015
Размер:
7.43 Mб
Скачать

чтобы это сделать, вам следует обрамить каждый набор вершин вызовами команд glBegin() и glEnd(). Аргумент, передаваемый glBegin(), определяет, какие графические примитивы создаются на основе вершин. Пример 2-3 задает вершины для полигона на рисунке 2-6.

Рисунок 2-6. Рисуем полигон или набор точек.

Пример 2-3 Конструирование полигона

glBegin(GL_POLYGON); glVertex2f(0.0,0.0); glVertex2f(0.0,3.0); glVertex2f(4.0,3.0); glVertex2f(6.0,1.5); glVertex2f(4.0,0.0);

glEnd();

Если бы вы указали GL_POINTS вместо GL_POLYGON в качестве примитивов, были бы построены пять точек, показанных на рисунке 2-6. В таблице 2-2 перечислены возможные аргументы команды glBegin() и соответствующие им типы примитивов.

void glBegin(GLenum mode);

Отмечает начало блока вершинных данных, описывающего геометрические примитивы. Тип примитивов задается аргументом mode, который может принимать значения, перечисленные в таблице 2-2.

Таблица 2-2. Значения аргумента mode (имена примитивов) для glBegin() и их смысл

Значение

Соответствующие примитивы

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

граница простого выпуклого полигона

 

 

На рисунке 2-7 показаны примеры всех геометрических примитивов, перечисленных в таблице 2-2. Обратите внимание, что в дополнение к точкам определено также несколько типов линий и полигонов. Безусловно, вы можете нарисовать один и тот же примитив различными методами. Как правило, выбираемый путь зависит от характера имеющихся вершинных данных.

Рисунок 2-7. Типы геометрических примитивов

Когда вы будете читать следующее описание, предполагайте, что между парой glBegin() и glEnd() задано n вершин (V[0], V[1], V[2], ..., V[n-1]).

GL_POINTS

Рисует точку на месте каждой из n вершин

 

Рисует серию несоединенных между собой отрезков. Рисуются отрезки между V[0] и

GL_LINES

V[1] , между V[2] и V[3], и так далее. Если n нечетно, то последний отрезок рисуется

 

между V[n-3] и V[n-2], а вершина n-1 игнорируется.

GL_LINE_STRIP

Рисует отрезок между V[0] и V[1], между V[1] и V[2], и так далее. Последний отрезок

 

 

GL_LINE_LOOP

GL_TRIANGLES

GL_TRIANGLE_STRIP

GL_TRIANGLE_FAN

GL_QUADS

GL_QUAD_STRIP

GL_POLYGON

рисуется между V[n-2] и V[n-1]. Таким образом, создается ломаная из n-1 отрезков. Если n < 2 не отображается ничего. Не существует ограничений на вершины, описывающие ломаную (или замкнутую ломаную). Отрезки могут любым образом пересекаться.

То же, что и GL_LINE_STRIP, но, кроме того, рисуется отрезок между V[n-1] и V[0], замыкающий ломаную.

Рисует серию треугольников (полигонов с тремя сторонами) используя вершины V[0], V[1] и V[2], затем V[3], V[4] и V[5], и так далее. Если n не кратно 3, последние 1 или 2 вершины игнорируются.

Рисует серию треугольников, используя вершины V[0], V[1] и V[2], затем V[2], V[1] и V[3] (обратите внимание на порядок), затем V[2], V[3], V[4], и так далее. Такой порядок гарантирует, что все треугольники будут иметь одинаковую ориентацию и, таким образом, соединенные треугольники могут сформировать часть поверхности. Сохранение ориентации очень важно для некоторых операций (например, для отсечения нелицевых граней). Для того, чтобы нарисовался хотя бы один треугольник n должно быть больше или равно 3.

То же, что и GL_TRIANGLE_STRIP, но порядок вершин следующий: V[0], V[1], V[2], затем V[0], V[2], V[3], затем V[0], V[3], V[4], и так далее.

Рисует серию четырехугольников (полигонов с четырьмя сторонами), используя вершины V[0], V[1], V[2], V[3], затем V[4], V[5], V[6], V[7], и так далее. Если n не кратно 4, последние 1, 2 или 3 вершины игнорируются.

Рисует серию прямоугольников, используя следующий порядок вершин: V[0], V[1], V[3], V[2], затем V[2], V[3], V[5], V[4], затем V[4], V[5], V[7], V[6] и так далее. n

должно быть не меньше 4, иначе ничего не будет нарисовано. Если n нечетно, последняя вершина игнорируется.

Рисует полигон, используя точки V[0], V[1], V[2], ..., V[n-1] в качестве вершин. n должно быть не меньше 3 или ничего нарисовано не будет. Кроме того, описываемый полигон не должен иметь самопересечений и должен быть выпуклым. Если вершины не удовлетворяют этим условиям, результат непредсказуем.

2.3.3.1 Ограничения на использование glBegin() и glEnd()

Наиболее важная информация о вершинах это их координаты, которые указываются командой glVertex*(). Вы также можете указывать для каждой вершины специфические данные, такие как цвет, вектор нормали, координаты текстуры или любую их комбинацию, используя специальные команды. Кроме того, некоторые другие команды допустимы между glBegin() и glEnd(). Таблица 2-3 содержит полный список этих команд.

Таблица 2-3. Команды, допустимые между вызовами glBegin() и glEnd().

Команда

Назначение

glVertex*()

установка координат вершины

glColor*()

установка текущего цвета

glIndex*()

установка текущего цветового индекса

glNormal*()

установка координат вектора нормали

glTexCoord*()

установка координат текстуры

glMultiTexCoord*ARB()

установка координат текстуры при мультитекстурировании

glEdgeFlag*()

контролирует рисование ребер

glMaterial*()

установка свойств материала

glArrayElement()

выделяет данные из массива вершин

glEvalCoords*(),

генерирует координаты

glEvalPoint*()

 

glCallList(), glCallLists()

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

 

 

Никакие другие команды недопустимы между glBegin() и glEnd(), и вызов большинства других команд OpenGL вызовет ошибку. Некоторые команды, связанные с массивами вершин, такие как glEnableClientState() и glVertexPointer() при вызове внутри glBegin() и glEnd() ведут к неопределенным результатам, но не обязательно генерируют ошибку. (Аналогично, функции оконной системы, связанные с OpenGL,

такие как функции glX*() ведут себя неопределенным образом между glBegin() и

glEnd().) Ошибки, связанные с употреблением недопустимых команд, достаточно трудно обнаруживать и поэтому таких употреблений следует избегать.

Обратите внимание, однако, что ограничения накладываются только на команды OpenGL и функции, связанные с ней. Вы можете свободно помещать другие языковые конструкции и вызовы между glBegin() и glEnd(). Пример 2-4, иллюстрирующий это, рисует окружность.

Пример 2-4. Языковые конструкции между glBegin() и glEnd()

#define PI 3.1415926535898 GLint circle_points=100; glBegin(GL_LINE_LOOP);

for(i=0;i<CIRCLE_POINTS;I++)

{

angle=2*PI*i/circle_points; glVertex2f(cos(angle),sin(angle));

}

glEnd();

Замечание: В примере приведен не самый эффективный способ рисования окружности, особенно, если вы планируете делать это часто. Используемые графические команды обычно достаточно быстры, но в приведенном коде для каждой вершины рассчитывается угол, и вызываются функции sin() и cos(). Кроме того, здесь присутствует наложение конца ломаной на ее начало. Если вам необходимо рисовать множество окружностей, вычислите координаты вершин единожды и создайте список отображения или используйте массив вершин.

Если только glVertex*() не используются для компиляции списка отображения, все они должны вызываться только внутри командных скобок glBegin() и glEnd(), иначе glVertex*() игнорируются. Если glVertex*() используются внутри списка отображения, то и в этом случае командные скобки должны присутствовать: они должны обрамлять либо обращения к glVertex*() внутри списка, либо команды исполнения готового списка (например, glCallList()).

Несмотря на то, что между glBegin() и glEnd() допустимо достаточно много команд, вершина создается только при вызове команды glVertex*(). В момент вызова glVertex*() OpenGL ассоциирует с создаваемой вершиной текущий цвет, координаты текстуры, информацию о векторе нормали и так далее. Чтобы убедиться в этом, посмотрите на следующий код. Первая точка рисуется красным цветом, вторая и третья

синим, несмотря на дополнительные команды изменения текущего цвета.

glBegin(GL_POINTS); glColor3f(0.0,1.0,0.0); //зеленый glColor3f(1.0,0.0,0.0); //красный

glVertex(...); glColor3f(1.0,1.0,0.0); //желтый glColor3f(0.0,0.0,1.0); //синий glVertex(...);

glVertex(...); glEnd();

Вы можете использовать любую комбинацию 24 версий команды glVertex*() внутри glBegin() и glEnd(), хотя в реальных приложениях вершинные данные имеют тенденцию сохранять свой формат и поэтому, обычно достаточно одной версии. Если в

вашем приложении вызовы команд установки параметров вершин имеют достаточно постоянную последовательность (например, glColor*, glVertex*, glColor*, glVertex* и так далее), вы можете получить выигрыш по производительности путем использования массивов вершин.

2.4 Основы управления состоянием

В предыдущей секции вы видели пример переменной состояния текущего RGBA – цвета, и как он может быть назначен примитиву. OpenGL управляет множеством переменных состояния. Объект может быть отображен с учетом освещения, текстурирования, удаления невидимых поверхностей, тумана, других механизмов (states), влияющих на его внешний вид, и каждый из этих механизмов имеет множество, ассоциированных с ним, переменных состояния.

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

Для включения или выключения многих механизмов используются 2 простые команды:

void glEnable (GLenum cap); void glDisable (GLenum cap);

glEnable() включает механизм, glDisable() выключает его. Существует более 40 величин, которые могут передаваться в качестве параметров glEnable() или glDisable(). Вот некоторые примеры: GL_BLEND (контролирует наложение RGBA – величин), GL_DEPTH_TEST (контролирует сравнение по глубине и обновление буфера глубины), GL_LINE_STIPPLE (применение шаблонов для линий) и GL_LIGHTING (освещение).

Вы также можете проверить включен или выключен определенный механизм:

GLboolean glIsEnabled (GLenum capability);

Возвращает GL_TRUE или GL_FALSE в зависимости от того включен или выключен запрашиваемый механизм.

Механизмы, которые вы только что видели, имеют два положения: включен или выключен. Однако большинство команд OpenGL устанавливает значения более сложных переменных состояния. Например, команда glColor3f() устанавливает 3 величины, которые являются частью механизма GL_CURRENT_COLOR. Существует 5 команд опроса, используемых для получения значений переменных из различных механизмов:

void glGetBooleanv (GLenum pname, GLboolean *params); void glGetIntegerv (GLenum pname, GLint *params); void glGetFloatv (GLenum pname, GLfloat *params); void glGetDoublev (GLenum pname, GLdouble *params); void glGetPointerv (GLenum pname, GLvoid *params);

Извлекают значения переменных состояния булевского типа, целого типа, дробного типа одинарной и двойной точности и типа указателя. Аргумент pname символическая константа, определяющая запрашиваемую переменную состояния, а params указатель на массив соответствующего типа, в который следует поместить возвращаемые данные. Например, чтобы получить текущий RGBA – цвет используйте glGetIntegerv(GL_CURRENT_COLOR, params) или glGetFloatv(GL_CURRENT_COLOR, params). Конверсия типов (если она необходима) автоматически производится для того, чтобы вернуть значения запрашиваемого типа. Эти команды опроса годятся для извлечения значений почти всех (но не всех) переменных состояния.

2.5 Отображение точек, линий и полигонов

По умолчанию, точка отображается как один пиксель на экране, линия рисуется сплошной, в один пиксель толщиной, полигоны рисуются со сплошной заливкой. Следующие параграфы разъясняют, как можно изменить эту ситуацию.

2.5.1 Подробно о точках

Для управления размером рисуемых точек используйте glPointSize() и укажите желаемый размер (в пикселях) как аргумент.

void glPointSize (GLfloat size);

Устанавливает длину и высоту (в пикселях) для визуализируемой точки, size должен быть больше 0.0 и, по умолчанию, равен 1.0.

Реальный набор пикселей на экране, который будет нарисован для различных размеров точки зависит от того, включен или выключен антиалиасинг. (Антиалиасинг это техника сглаживания рисуемых точек и линий.) Если антиалиасинг выключен (а он выключен по умолчанию), дробные размеры точек округляются до ближайшего целого и для каждой точки на экране будет нарисован квадратный регион пикселей. Таким образом, если размер точки равен 1.0, будет нарисован квадрат с размерами 1 x 1 пиксель, если размер точки 2.0 будет нарисован квадрат с размерами 2 x 2 пикселя и так далее.

Когда антиалиасинг включен, рисуется циркулярная группа пикселей, и пиксели по

границе обычно имеют цвет с пониженной интенсивностью для придания границе гладкого вида. В этом режиме дробные размеры точек до целого не округляются (рисунок 2-8).

Рисунок 2-8. Точки разного размера в разных режимах

Большинство реализаций OpenGL поддерживают точки очень большого размера. Вы можете запрашивать минимальный и максимальный размеры для несглаженных точек, используя аргумент GL_ALIASED_POINT_SIZE_RANGE в команде glGetFloatv(). Точно

так же вы можете запрашивать минимальный и максимальный размеры сглаженных точек, используя в той же команде аргумент GL_SMOOTH_POINT_SIZE_RANGE.

Допустимые размеры сглаженных точек дискретно меняются в диапазоне от минимума до максимума. Вызвав glGetFloatv() с параметром

GL_SMOOTH_POINT_SIZE_GRANULARITY, вы узнаете, с какой точностью сглаженные точки отображаются на экране, то есть величину минимального изменения размера точки внутри диапазона от минимума до максимума, имеющую видимый эффект (величину гранулирования). Например, если вы запрашиваете glPointSize(2.34), а величина гранулирования равна 0.1, размер точки будет округлен до 2.4.

Замечание: В некоторых случаях довольно трудно получить указанные выше параметры, поскольку соответствующие константы могут быть не определены в заголовочных файлах, поставляемых с вашим компилятором или реализацией OpenGL. Однако, как правило, в этих файлах определена константа

GL_POINTS_SIZE_RANGE (по смыслу соответствующая GL_SMOOTH_POINT_SIZE_RANGE) и GL_POINT_SIZE_GRANULARITY (соответствующая GL_SMOOTH_POINT_SIZE_GRANULARITY).

То же касается и параметров линий (максимальной и минимальной толщины и гранулярности). Вполне возможна ситуация, когда в заголовочных файлах определены лишь константы GL_LINE_WIDTH_RANGE (по результату аналогичная

GL_SMOOTH_LINE_WIDTH_RANGE) и GL_LINE_WIDTH_GRANULARITY (соответствующая

GL_SMOOTH_LINE_WIDTH_GRANULARITY). Вообще подобные сложности могут возникать и в других случаях из-за различий в реализациях, версиях библиотеки, средствах разработки и так далее. Благо, они не настолько часты.

2.5.2 Подробно о линиях

В OpenGL вы можете рисовать линии различной толщины, а также линии, имеющие шаблон пунктирные, штриховые, штрих пунктирные и так далее.

2.5.2.1Толщина линий

void glLineWidth (GLfloat width);

Устанавливает толщину линии в пикселях, width должно быть больше 0.0 и по умолчанию равно 1.0.

Реальная визуализация линий зависит от механизма антиалиасинга по аналогии с точками. Без антиалиасинга значения толщины равные 1, 2 и 3 задают линии на экране в 1, 2 и 3 пикселя толщиной. При включенном антиалиасинге для толщины допустимы

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

поддерживаемых значений толщины несглаженных линий посредством команды glGetFloatv() с аргументом GL_ALIASED_LINE_WIDTH_RANGE. Чтобы получить

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

Замечание: Имейте в виду, что по умолчанию линии имеют толщину в 1 пиксель, так что они кажутся толще при низком разрешении монитора и тоньше при высоком. Для мониторов это, как правило, не проблема, но если вы используете OpenGL для вывода изображения на другое устройство, например, плоттер высокого разрешения, линия в 1 пиксель толщиной может быть практически неразличима. В подобных случаях приходится вычислять значения толщины для каждого разрешения, принимая в расчет физический размер пикселя на экране или устройстве.

Дополнительно: При рисовании несглаженных линий следует учесть, что их толщина измеряется вовсе не перпендикулярно самой линии. Вместо этого толщина измеряется в направлении оси ординат при условии, что |y2-y1|<|x2-x1|(где (x1,y1) и (x2,y2) - координаты концов отрезка) и в направлении оси абсцисс в иных случаях. Рисование

сглаженного отрезка определенной толщины полностью эквивалентно рисованию закрашенного прямоугольника соответствующей высоты, центрированного отрезку в один пиксель.

2.5.2.2 Шаблоны отрезков

Чтобы задать шаблон отрезка (например, для получения пунктирных или штриховых отрезков) следует использовать команду glLineStipple() и затем включить шаблонирование командой glEnable().

glLineStipple(1,0x3F07); glEnable(GL_LINE_STIPPLE);

void glLineStipple (Glint factor, GLushort pattern);

Устанавливает текущий шаблон для отрезка. Аргумент pattern это 16-битная серия из нулей и единиц, определяющая, как будет рисоваться отрезок. Она повторяется по необходимости для шаблонирования всего отрезка. Единица означает, что соответствующая точка отрезка будет нарисована на экране, ноль означает, что точка нарисована не будет (на попиксельной основе). Шаблон применяется, начиная с младшего бита аргумента pattern. Шаблон может быть растянут с учетом значения фактора повторения factor. Каждый бит шаблона при наложении на отрезок расценивается как factor битов того же значения, идущих друг за другом. Например, если в шаблоне встречаются подряд три единицы, а затем два нуля и factor равен 3, то шаблон будет трактоваться как содержащий 9 единиц и 6 нулей. Допустимые значения аргумента factor ограничены диапазоном от 1 до 256. Шаблонирование должно быть включено передачей аргумента GL_LINE_STIPPLE в функцию glEnable(). Оно блокируется передачей того же аргумента в glDisable().

Итак, в предыдущем примере с шаблоном равным 0x3F07 (что в двоичной системе счисления соответствует записи 0011111100000111) отрезок будет выведен на экран, начинаясь (по порядку) с 3 нарисованных пикселей, 5 отсутствующих, 6 нарисованных и 2 отсутствующих (если вам кажется, что мы применили шаблон задом - наперед вспомните, что он применяется, начиная с младшего бита). Если длина нашего отрезка на экране больше 16 пикселей, начиная с 17-го, шаблон будет применен заново и так далее до конца отрезка. Если бы factor был равен 2, шаблон был бы растянут, и отрезок выглядел бы следующим образом: вначале 6 нарисованных пикселей, затем 10 отсутствующих, 12 нарисованных и 4 отсутствующих. На рисунке 2-9 показаны отрезки, нарисованные с применением различных шаблонов и факторов повторения шаблона. Если шаблонирование заблокировано, все отрезки рисуются таким же образом, как если бы шаблон был установлен в 0xFFFF, а фактор повторения в 1. Обратите внимание, что шаблонирование может применяться в комбинации с линиями различной толщины.

Рисунок 2-9. Шаблонированные отрезки

Если рисуется ломаная (с помощью GL_LINE_STRIP или GL_LINE_LOOP) то шаблон накладывается на нее непрерывно, независимо от того, где кончается один сегмент и начинается другой. В противовес этому для каждой индивидуальной линии (рисуемой с помощью GL_LINES) шаблон начинается заново, даже если все команды указания вершин вызываются внутри одного блока glBegin() glEnd().

Пример 2-5 иллюстрирует результаты экспериментов с различными шаблонами и значениями толщины отрезков. Он также показывает разницу между рисованием ломаной и отдельных отрезков. Результаты работа программы показаны на рисунке 2- 10.

Рисунок 2-10. Эксперименты с шаблонами и толщиной отрезков

Пример 2-5. Шаблоны отрезков. Файл lines.cpp

#include

#define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES);glVertex2f((x1),(y1));glVertex2f((x2),(y2));glEnd();

void init(void)

{

glClearColor(1.0,1.0,1.0,0.0); glShadeModel(GL_FLAT);

}

void display(void)

{

int i;

glClear(GL_COLOR_BUFFER_BIT);

//Черный цвет для всех линий glColor3f(0.0,0.0,0.0);

glEnable(GL_LINE_STIPPLE);

//В первом ряду три линии с разными шаблонами glLineWidth(1.0);

glLineStipple(1,0x0101); //Пунктирная drawOneLine(50.0,125.0,150.0,125.0); glLineStipple(1,0x00FF); //Штриховая drawOneLine(150.0,125.0,250.0,125.0); glLineStipple(1,0x1C47); //Штрих-пунктирная drawOneLine(250.0,125.0,350.0,125.0);

//Во втором ряду три толстые линии с аналогичными шаблонами glLineWidth(5.0);

glLineStipple(1,0x0101); //Пунктирная drawOneLine(50.0,100.0,150.0,100.0); glLineStipple(1,0x00FF); //Штриховая drawOneLine(150.0,100.0,250.0,100.0); glLineStipple(1,0x1C47); //Штрих-пунктирная drawOneLine(250.0,100.0,350.0,100.0);

//В третьем ряду шесть штрих-пунктирных линий, объединенных в ломаную glLineWidth(1.0);

glLineStipple(1,0x1C47); //Штрих-пунктирная glBegin(GL_LINE_STRIP);

for (i=0;i<7;i++)

glVertex2f(50.0+((GLfloat)i*50.0),75.0);

glEnd();

//В четвертом ряду шесть независимых линий того же шаблона for (i=0;i<6;i++)

{

drawOneLine(50.0+((GLfloat)i*50.0),50.0,50.0+((GLfloat)(i+1)*50.0),50.0);

}

//В пятом ряду 1 штрих-пунктирная линия с фактором повторения=5 glLineStipple(5,0x1c47);

drawOneLine(50.0,25.0,350.0,25.0);

glDisable(GL_LINE_STIPPLE); glFlush();

}

void reshape(int w,int h)

{

glViewport(0,0,(GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0,400.0,0.0,150.0);

}

int main(int argc, char **argv)

{

glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(400,150); glutInitWindowPosition(100,100); glutCreateWindow("Line Stipple Patterns"); init();

glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop(); return 0;

}

2.5.3 Подробнее о полигонах

Обычно полигоны рисуются в виде закрашенной области пикселей, лежащих внутри их границ, но также они могут быть нарисованы в виде самой границы (ломаной) или просто в виде точек, соответствующих их вершинам. Возможна как полная заливка, так и применение различных шаблонов. Если смежные полигоны разделяют ребро или вершину, то пиксели, соответствующие на экране этому ребру или вершине рисуются только один раз, то есть они включаются только в один из полигонов. Это делается для того, чтобы для частично прозрачных полигонов ребра не рисовались дважды это может привести к тому, что такие ребра будут выглядеть темнее или ярче (в зависимости от их цвета). Заметьте, что это может привести к тому, что узкие полигоны при рисовании будут иметь дыры в одном или более рядов или столбцов пикселей. Антиалиасинг для полигонов более сложен, чем для точек и отрезков.

2.5.3.1 Закрашенные полигоны, полигоны в виде линий или точек

У полигона две стороны или гранилицевая и обратная, и он может быть визуализирован по-разному в зависимости от того, которая из сторон видна наблюдателю. Это позволяет вам создавать изображения таким образом, как если бы вы заглядывали внутрь объекта у которого лицевые и обратные части рисуются по- разному (например, сфера, разрезанная пополам). Полигон также считается лицевым или обратным в зависимости от того, какой из граней он повернут к наблюдателю. По умолчанию, лицевые и обратные грани изображаются одинаково. Чтобы это изменить, а также, чтобы рисовать только вершины или границы полигона, используйте команду glPolygonMode().

Соседние файлы в предмете Компьютерная Графика