Смекни!
smekni.com

Построение реалистичных трехмерных изображений в стандарте OpenGL (стр. 2 из 3)

void glNormal3 [b s i f d] (type coords)

void glNormal3 [b s i f d]v (type coords)

которые присваивают значения координат, заданных параметрами coords, вектору нормали. Аргументы типов GLbyte, GLshortи GLintпреобразуются в формат с плавающей точкой и ограничиваются диапазоном [-1.0, 1.0]. В общем случае нормаль, определяемая этими командами, не имеет единицы длины. Однако если включен режим нормализации (выполнена команда glEnableс аргументом GL_NORMALIZE), то нормали, определенные при помощи этой команды, нормализуются после трансформации. По умолчанию нормализация заблокирована, а вектор нормали имеет координаты (0.0, 0.0, 1.0).


Рис. 5.Векторы нормали Рис. 6.Грань и нормаль к ней

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

Свойства материала

Различные материалы по-разному отражают свет. Металл это делает хорошо, а пластиковые поверхности обычно выглядят тусклыми. Кроме того, некоторые поверхности сами излучают свет, например, фосфор. Задавая различные параметры материала, можно управлять тем, насколько блестящим он будет выглядеть, и будет ли он сам излучать свет. На рис. 7 изображены 24 чайника, освещаемые одним источником света.

Рис. 7 Объекты с различными свойствами материала


Что здесь для нас интересно? Прежде всего – сами свойства. В приведенном фрагменте мы устанавливали рассеянный, диффузный и зеркальный цвета материала, причем, только для его лицевой поверхности. Можно ли задавать какие-нибудь еще параметры? Для ответа на этот вопрос рассмотрим команды:

void glMaterial [i f] (GLenum face, GLenum pname, GLtype* params)

и

void glMaterial [i f] v (GLenum face, GLenum pname, GLtype* param)

которые позволяют определить различные свойства материала. Какие именно – зависит от используемых параметров. Параметры материала, как и во многих других случаях, различаются для лицевой и обратной поверхностей. Параметры лицевой поверхности используются для точек, линий, битовых массивов и всех многоугольников, когда заблокировано двустороннее освещение или только для лицевых, если двустороннее освещение разрешено. Параметры для обратных поверхностей определяют затенение невидимых многоугольников, только когда разрешено двустороннее освещение. К каким поверхностям применяются задаваемые параметры, определяется аргументом face:

GL_FRONT лицевые

GL_BACK обратные

GL_FRONT_AND_BACK и те и другие

Аргумент рnameопределяет, какие параметры материала будут обновляться и может принимать только одно значение – GL_SHININESS, задающее степень зеркального отражения материала для первой версии команды и следующие значения для второй:


Параметр Значение
GL_AMBIENT Параметр paramsсодержит четыре целых или вещественных значения цветов RGBA, которые определяют рассеянный цвет материала. По умолчанию значение рассеянного цвета равно (0.2, 0.2, 0.2, 1.0)
GL_DIFFUSE Параметр paramsсодержит четыре целых или вещественных значения RGBA, которые определяют цвет диффузного отражения материала. По умолчанию значение диффузного цвета равно (0.8, 0.8, 0.8, 1.0)
GL_SPECULAR Параметр paramsсодержит четыре целых или вещественных значения RGBA, которые определяют цвет зеркального отражения материала. По умолчанию значение зеркального цвета равно (0.0, 0.0, 0.0, 1.0)

Последний аргумент – param (s) содержит значение(я), которые присваиваются соответствующему параметру.

Из приведенного описания видно, что, задавая параметры материала, можно управлять тем, насколько блестящим будет выглядеть материал и будет ли он самостоятельно излучать свет. Другими словами, можно определять отражающие свойства материала. Наиболее часто учитываемыми в различных моделях являются диффузный и зеркальный отраженный свет, поскольку диффузное отражение придает объекту его естественный цвет, а зеркальное определяет отражающие свойства поверхности: на очень блестящей поверхности зеркальное отражение приводит к появлению резко очерченных бликов, а для менее блестящих объектов выглядит более тускло.

Таким образом, чтобы объект выглядел блестящим, необходимо сузить угол зеркального отражения, а для тусклых поверхностей наоборот расширить его. Используемые при моделировании математические зависимости показывают, что интенсивность отраженного света определяется не углом отражения, а косинусом этого угла. Например, для модели Фонга зависимость имеет вид

Is= w (i, λ) cosnα,


где w (i, λ) – кривая отражения, представляющая отношение зеркально отраженного света к падающему как функцию угла падения i и длины волны λ, а n– степень, аппроксимирующая пространственное распределение зеркально отраженного света. Зачем я все это описываю? Дело в том, что в OpenGL имеется возможность косвенного управления углом зеркального отражения. Осуществляется это при помощи параметра GL_SHININESS, позволяющего определять именно значение n.

Каждый параметр устанавливается отдельным вызовом команды и, следовательно, не зависит от остальных. Сложность здесь только одна – как определить необходимые значения задаваемых цветов, чтобы получить поверхность того материала, который требуется. Наряду с только чторассмотренной командой, для установки параметров материала в OpenGL реализована еще одна:

void glColorMaterial (GLenum face, GLenum mode)

Уэтойкомандыаргументfaceможетприниматьтежезначения, чтоивкомандеglMaterial*,ааргументmode –толькозначения GL_AMBIENT_AND_DIFFUSE, GL_AMBIENT, GL_EMISSION, GL_DIFFUSE и GL_SPECULAR. По умолчанию используется GL_AMBIENT_AND_ DIFFUSE. Если разрешен режим GL_COLOR_MATERIAL (вызовом команды glEnableс соответствующим аргументом), то параметры поверхностей материала, заданные аргументами modeи face, принимают значения текущего цвета. В этом случае можно изменять параметры материала для каждой вершины, используя только команду glColor*, без дополнительного вызова glMaterial*,что в некоторых случаях является более удобным.

Грани

Граньюназывается сторона многоугольника. Причем в качестве многоугольника могут выступать как простейший треугольник, так и сложный многоугольник. Единственным условием для них является то, что многоугольник любой степени сложности должен лежать в одной плоскости. Отсюда очевидно, что трехмерные объекты состоят из нескольких плоских многоугольников. И для того, чтобы изобразить «гладкий» конус потребуется достаточно большое число плоских многоугольников. Каждый многоугольник имеет две стороны, т.е. две грани, – лицевую и обратную. И на обеих можно «рисовать». Причем, если мы «рисуем» на лицевой грани, а она в данный момент не видна, то мы только тратим время. Очевидно, что только одна грань может быть видима в окне в текущий момент времени. Для того чтобы не тратить время на воспроизведение невидимых граней, во всех графических системах реализованы механизмы, позволяющие различать лицевые и обратные грани. Естественно, что такой механизм есть и в OpenGL. Причем, в отличие от многих других систем, – очень гибкий. При рассмотрении многоугольных примитивов уже говорилось о важности порядка обхода вершин. И связано это именно с гранями – лицевой и обратной. На рис. 8, на котором представлены два возможных способа обходя вершин.

Рис. 8.Обход вершин по часовой стрелке и против

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

voidglFrontFace (Glenummode)

которая позволяет определить, какая грань берется в качестве лицевой, в зависимости от направления обхода многоугольника – по часовой стрелке или против. Направление обхода задается параметром mode, который может принимать значения GL_CW– по часовой стрелке и GL_CCW– против часовой стрелки (установлено по умолчанию).

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

voidglCullFace (GLenummode)

эта команда позволяет указать грань – лицевую или обратную. В качестве граней могут использоваться треугольники, квадраты, многоугольники или прямоугольники. Являются они лицевыми или обратными, задается командой glFrontFace. Какие грани будут отображаться, задается параметром mode, который может принимать одно из двух значений: GL_FRONT– для лицевых и GL_BACK– для обратных граней (последнее используется по умолчанию).

Для того чтобы разрешить OpenGL отбирать изображаемые грани, необходимо выполнить команду glEnable с аргументом GL_CULL_FACE. Блокировка этого режима как обычно осуществляется командой glDisableс тем же аргументом.

На рис. 9 представлено окно приложения Faces, для случая, когда направления обхода вершин и режима выбора граней используются значения по умолчанию. Режим отбора граней – заблокирован.

Рис. 9. Объект, у которого видны и лицевая и обратная грани.