М. Ву, Т. Девис, Дж. Нейдер, Д. Шрайнер - OpenGL. Руководство по программированию (Библиотека программиста) (2006) (1124363), страница 16
Текст из файла (страница 16)
2.12, а затем рисуют треугольники. Конечно, тогда не будет работать функция о)Ро(уйопМобе() для рисования контура, так как будут отображены все внутренние контуры треугольников. Для решения этой проблемы можно указать Орепби какие отдельные вершины определяют границы. На основании этой инфориации Орепць назначает каждой вершине бит-идентификатор того, принадлежит она границе или нет. Затем при рисовании многоугольника в режиме О1 11НЕ неграничные отрезки не рисуются. На рис. 2.12 штриховые линии показывают добавочные нерисуемые границы. Рис. 2.12. Разделение невыпуклых многоугольников По умолчанию все вершины помечаются как определяющие границу, но можно вручную контролировать установку признака грапицск с помощью команды я1Ебяер1аб*().
Эта команда используется между операторными скобками к1Вей(п () и а1Епб () и применяется ко всем вершинам, определяемым за ней, до следующего вызова В1ЕббеР1аа(). Она применима только к вершинам многоугольников, треугольников и четырехугольников, но не к вершинам, определенным для разбивки треугольников или прямоугольников. чоЫ В1Еббер1аа(СЕЬоо1еап))ай); чоЫ а1ЕббеГ1айч(сопзг 01.Ьоо!сап "~1ай); Определяет, относится ли вершина к границе многоугольника. Если ((ай равен 61 Тй() Е, флаг краев устанавливается в ТК0 Е (по умолчанию) и любая вершина полагается относящейся к границе до следующего вызова этой функции с~!ад, равным 61 ГА15Е. Например, программа из листинга 2.7 рисует контур, показанный на рис.
2.13. Листинг 2.7. Пометка границ многоугольника а)Ро(увопиобе(б1 Равит АНО ВАСК, В( Г(НЕ); а)зей(п(бг РО(убОН): й(Ебаег(аа(йь таЧЕ); В1уегтех)тч(Ч9); В1Ебаег1ак(ьс ГА(5Е); В)уегтехзтч(Ч1); В1Ебвег1ак(61 Тазе); В)Чегтехзтч(Ч2)', а1Епб(); 72 Глава 2 ° Управление состоянием и рисование геометрических объектов чг Ч1 чо Рис. 2.13. Очерчивалие многоугольника при использовании флага краев Векторы нормали Вектор йормили (или, коротко, нормаль) — вектор в направлении, перпендикулярном к поверхности.
Для плоских поверхностей это направление одинаково для всех точек, но для кривых поверхностей оно может быть различным. Орепб?. позволяет определять нормали для каждой вершины или каждого многоугольника. Вершины одного многоугольника могут иметь одинаковые (для плоских поверхностей) или различные (для кривых поверхностей) нормали. Векторы нормалей для объектов определяют ориентацию их поверхностей в пространстве — в частности, относительно источников света. Эти векторы используются Орепб?.
для расчета, сколько света получает объект в вершинах. Освещение — отдельная большая тема — обсуждается в главе 5, но поскольку нормали определяются вместе с заданием геометрии объекта, рассматриваются они здесь. Функция а1йогйа1*() используется для установки текущей нормали, определяемой значением аргумента. Последую<цие вызовы а1Чегтех* О связывают определяемые вершины с текущей нормалью. Часто каждая вершина имеет собственную нормаль, что влечет серию различных вызовов, как, например, в листинге 2.8. Листинг 2.8. Нормали к поверхности в вершинах В1веа(п <61 РО(У60М); В)йогов(З(ч<пв); В!Чег<ехЗ(ч<чз); В1йогва<3(ч(п1); В1Чег(ехЗ(ч(ч1); В1йогва13(ч(п2); В1чег(ехЗ<ч(ч2); В1йагва13(ч(пЗ); Х1Чег(ехЗ(ч(чЗ): В1Епо(); чоЫ а1йага<а13(Ьз?г??)(ТУРЕ лх, ТУРЕ лу, ТУРЕ пг); чо?<? к1йогва13(Ьз?<??)ч(сонат ТУРЕ "о); устанавливает текущие векторы нормали согласно аргументам.
Не векторные версии (без ч) имеют три аргумента, определявшие вектор нормали (лх, лу, ва). Кроме того, есть векторная версия функции (с ч), принимающая массив из трех элементов для определения нужной нормали. Скалярные версии Ь, з и 1 принимают значения в диапазоне [-1.0, 1.0]. Массивы вершин 73 Нет никакой магии в нахождении нормалей к объекту — это некоторые вычисления, которые включают в себя вычисление производных. Но схожий эффект дают приемы, раскрытые в приложении Д. Если это для вас не откровение, или если вы предпочитаете готовые результаты, или если вы не хотите использовать освещение, можете и нс читать это приложение. Конечно, в любой точке поверхности есть два перпендикулярных вектора, направленных в противоположных направлениях.
Нормалью считается тот, что ориентирован вовне от моделируемой поверхности. Если нужно обратить внешнюю и внутреннюю части модели, измените каждый вектор нормали из (х, у, х) В ( — х, — у, -х). Помните, что векторы нормали определяют только направление н их длина не имеет значения. Нормали могут быть любой длины, но в конечном счете перед вычислением освещенности они все преобразуются к единичной длине. (Такой вектор называется нормализованным.) В общем, вам нужны нормализованные векторы нормали.
Для получения вектора нормали единичной длины разделите каждую его составляющую х, у, г на длину нормали: )Т'7.* . Векторы нормали нормируются каждый раз при выполнении модельных преобразований — а именно при повороте и параллельном переносе (см, главу 3). Если вы выполняете нестандартные преобразования (такие, как масштабирование или умножение на матрицу сдвига) или определяете несдиничные нормали, можно автоматически нормализовать ваши векторы нормали после преобразований— командой Х1ЕпаЫе(ОЕ ИОРИАЕ17Е). Если вы используете единичные нормали и выполняете только однородное масштабирование (одинаковое масштабирование значений х, у и г), включите режим ОЕ РЕ5САЕЕ ИОРИАЕ.
Тогда нормали будут масштабироваться к единичной длине постоянным множителем, полученным из матрицы модельно-видовых преобразований. Помните, что автоматическая нормализация или масштабирование обычно требуют дополнительных вычислений, которые могут снизить производительность ваших приложений. Масштабирование нормалей с помощью ОЕ РЕ5САЕЕ ИОРИАЕ обычно менее времяемкое, чем полная нормализация с помощью 61 ИОРИАЕ! 7Е. По умолчанию автоматическая нормализация и масштабирование отключены. Массивы вершин Разумеется, вы уже заметили, что в ОрепбЕ рисование графических примитивов складывается из множества вызовов функций. Так, рисование 20-стороннего многоугольника сопровождается 22 вызовами: один — к1йея1п О, по одному вызову для каждой вершины, и, наконец, вызов я1Е по' () .
Дополнительная информация, такая как в двух предыдущих примерах кода (флаг краев или нормали к поверхности), может привести к удвоению или утроению числа вызовов функций, 74 Глава 2 ° Управление состоянием и рисование геометрических объектов необходимых для построения одного геометрического объекта, и, соответственно, к большим задержкам и падению производительности. Дополнительной проблемой является избыточная обработка вершин, общих для смежных многоугольников. Например, куб на рис. 2.14 имеет 6 лицевых граней и 8 общих вершин.
И, если действовать стандартно, каждая вершина будет описана три раза — для каждой лицевой грани, к которой она относится. Таким образом, будет обработано 24 вершины, в то время как достаточно восьми. Рис. 2.14. Шесть граней. Восемь общих вершин ОрепСЕ предоставляет набор функций для работы с массивами вершин. Массивы позволяют определять большое количество информации, связанной с вершинами, и получать доступ к этим данным посредством небольшого количества вызовов функций. В нашем примере все 20 вершин в 20-стороннем многоугольнике могут быть помещены в один массив и обработаны одной функцией. Если для каждой вершины также определены векторы нормалей, все 20 нормалей к поверхности могут быть помещены в другой массив и также обработаны одним вызовом.
Объединение данных в массивы увеличивает производительность приложений за счет безызбыточной обработки общих вершин и минимизации числа вызовов. (Общие вершины не поддерживаются всеми реализациями ОрепС1.) ПРИМЕЧАНИЕ Массивы вершин стали стандартом в Орепбь версии 1.1. В версии 1М добавлена поддержка хранении в них координат тумана и вторичных цветов.
При обработке массивов вершин геометрических объектов выделяются три шага: 1. Объявляем восемь массивов, каждый из которых хранит данные различных типов: координаты вершин, нормали к поверхности, РСВА-цвета, вторичные цвета, индексные цвета, координаты тумана, координаты текстур или флаги краев многоугольников. 2.
Помещаем данные в массив или массивы. Доступ к массивам осуществляется по адресу в памяти. В клиент-серверной модели эти данные сохраняются в адресном пространстве памяти клиента. 3. Рисуем геометрию на основе данных. ОрепСЕ получает данные из всех активированных массивов с помощью различных указателей. В клиент-серверной модели данные перемещаются в адресное пространство сервера.