Курсовая работа: Построение реалистичных трехмерных изображений в стандарте OpenGL
Рис. 8. Обход вершин по часовой стрелке и против
После того как многоугольник спроецирован в окно, библиотека OpenGL «смотрит», в какой последовательности обходятся вершины многоугольника: если они обходятся по часовой стрелке, то видимой является одна из граней; если против часовой стрелки, то другая. Библиотека OpenGL, в отличие от многих других графических библиотек, позволяет программисту самому определять, какую грань считать лицевой, а какую обратной. Осуществляется это при помощи команды
void glFrontFace (Glenum mode)
которая позволяет определить, какая грань берется в качестве лицевой, в зависимости от направления обхода многоугольника – по часовой стрелке или против. Направление обхода задается параметром mode, который может принимать значения GL_CW – по часовой стрелке и GL_CCW – против часовой стрелки (установлено по умолчанию).
Кроме возможности самостоятельного определения типа грани – лицевая или обратная, OpenGL предоставляет также механизм, позволяющий исключить из процесса вывода грани одного типа.
void glCullFace (GLenum mode)
эта команда позволяет указать грань – лицевую или обратную. В качестве граней могут использоваться треугольники, квадраты, многоугольники или прямоугольники. Являются они лицевыми или обратными, задается командой glFrontFace. Какие грани будут отображаться, задается параметром mode, который может принимать одно из двух значений: GL_FRONT – для лицевых и GL_BACK – для обратных граней (последнее используется по умолчанию).
Для того чтобы разрешить OpenGL отбирать изображаемые грани, необходимо выполнить команду glEnable с аргументом GL_CULL_FACE. Блокировка этого режима как обычно осуществляется командой glDisable с тем же аргументом.
На рис. 9 представлено окно приложения Faces, для случая, когда направления обхода вершин и режима выбора граней используются значения по умолчанию. Режим отбора граней – заблокирован.
Рис. 9. Объект, у которого видны и лицевая и обратная грани.
Источник света
Рассмотрим, как и какие параметры источника света можно устанавливать. Начнем с команды glLight*, значения аргументов которой зависят от того, работаем мы с ее скалярной или векторной версией.
void glLight[if] (GLenum light, GLenum pname, GLfloat param)
Аргумент light определяет номер источника света, общее число которых зависит от реализации. В качестве значения этого параметра следует использовать символическое имя GL_LIGHTi, где i лежит в диапазоне от 0 до GL_MAX_LIGHTS, которое не может быть больше восьми. Аргумент pname является символической константой, определяющей устанавливаемый параметр:
GL_SPOT_EXPONENT | Параметр param содержит единственное целое или вещественное значение, которое задает распределение интенсивности света. Доступны значения из диапазона [0, 128]. Эффективность интенсивности света ослабевает пропорционально косинусу угла между направлением от источника и нормалью в вершине (рис. 3). Чем больше это значение, тем более сфокусирован источник света. По умолчанию установлено значение 0, что соответствует рассеянному свету |
GL_SPOT_CUTOFF | Параметр param является целым или вещественным значением, которое определяет максимальный угол разброса источника света. Доступны значения из диапазона [0, 90] и 180. По умолчанию используется значение 180, что соответствует рассеянному свету |
Аргумент param определяет значение, которое устанавливается для параметра pname источника light.
После того как установлены параметры источников света, эти источники можно включать и выключать в любое время. Источник света i включается или выключается командами glEnable или glDisable с аргументом GL LIGHTi, который определяется как GL_LIGHTi = GL_LIGHT0 + i.
Определение параметров источников света во многом подобно установке свойств материала. Каждый параметр задается отдельно, а если какой-либо не определен явным образом, то он все равно участвует в процессе освещения со значением, установленным по умолчанию. Отличающиеся параметры интуитивно понятны, и на первом этапе работы с источниками света некоторые трудности может вызвать только тот, который определяет максимальный угол разброса, – GL_SPOT_CUTOFF. Но и он становится совершенно понятным, если посмотреть на рис. 10: чем больше это значение, тем более «рассеянным» становится свет от источника.
Рис. 10. Углы разброса источника света
Рис. 11. Три видимых источника света и один невидимый – фоновый
Возможности OpenGL по поддержке режима освещения не ограничиваются заданием параметров материала и источников света. Имеется возможность определить модель освещения.
Модель освещения
Параметры модели освещения задаются командами
void gILightModelfi f] (GLenum pname, GLenum param)
void glLightModel [i f] v (GLenum pname, contst GLtype* params)
Аргумент pname определяет единственное значение параметра модели освещения и может принимать следующие значения:
GL_LIGHT_MODEL_LOCAL_VIEWER | Параметр param содержит единственное булевское значение, определяющее местоположение наблюдателя. Если param=FALSE, то направление обзора считается параллельным оси – z и направленным вдоль нее, независимо от действительного положения в видовых координатах. В противном случае (TRUE) предполагается, что наблюдатель находится в начале видовой системы координат. По умолчанию параметр param установлен в FALSE |
GL_LIGHT_MODEL_TWO_SIDE |
Параметр param представляет единственное булевское значение, которое определяет расчет освещенности многоугольников для одной или двух граней. Это не влияет на расчет освещенности для точек, линий или битовых массивов. Если param=FALSE, то задано одностороннее освещение, и в уравнении освещения используются только параметры лицевой грани материала. В противном случае (TRUE) задается двухстороннее освещение. В этом случае освещенность вершин обратной грани многоугольников рассчитывается на основе параметров обратной грани материала, и их нормали направлены в противоположные стороны. Освещенность вершин лицевой грани многоугольника всегда рассчитывается на основе параметров лицевой грани материала без изменения их нормалей. По умолчанию FALSE |
Аргумент param определяет значение, которое присваивается параметру модели освещения, заданному параметром pname.
Подведем некоторый итог. В режиме RGBA цвет освещенной вершины определяется суммой интенсивностей эмиссии материала, рассеянного отражения материала и полной фоновой интенсивности модели освещения. Вклад каждого источника света складывается из трех составляющих: фоновой, диффузной и зеркальной. Фоновая составляющая складывается из фонового отражения материала и фоновой интенсивности света. Диффузная составляющая определяется диффузным отражением материала, диффузной интенсивностью источника света и нормализованным вектором нормали. И, наконец, зеркальная составляющая определяется зеркальным отражением материала, зеркальной интенсивностью источника света и нормализованными векторами от вершины к источнику света и к наблюдателю. Вклад всех трех составляющих уменьшается в зависимости от расстояния до источника, от направления на него, экспоненциального разброса и угла разброса источника света. Компонент альфа результирующего цвета устанавливается в значение альфа диффузного отражения материала.
Кроме рассмотренных возможностей моделирования освещения объектов, которые непосредственно поддерживаются OpenGL, для придания большей реалистичности следует учитывать также такие факторы, как прозрачность некоторых материалов и, наоборот, полную непрозрачность, которая приводит к появлению теней. Эти возможности OpenGL непосредственно не поддерживаются, и их учет полностью ложится на плечи программистов. Рассмотрим некоторые аспекты этих вопросов.
Поверхности, пропускающие свет
реалистический изображение нормаль свет
Как уже отмечалось в начале главы, поверхности могут обладать не только свойствами зеркального и диффузного отражения, но и аналогичными свойствами пропускания. Направленное (зеркальное) пропускание света происходит сквозь прозрачные вещества, например, воду или стекло. Через них предметы обычно видны хорошо, несмотря на то, что лучи света отклоняются от своего первоначального направления (рис. 12). Если же свет при пропускании через вещество рассеивается, то мы имеем диффузное пропускание. Такие вещества кажутся полупрозрачными или матовыми, а объект, если смотреть на него сквозь такое вещество, будет выглядеть нечетким или искаженным.
Рис. 12. Эффект преломления
Именно с преломлением луча связан тот факт, что торчащая из воды палка кажется согнутой. Преломление рассчитывается по закону Снеллиуса, который утверждает, что падающий и преломленный лучи лежат в одной плоскости, а углы падения и преломления связаны соотношением:
η1sinθ=η2sinθ’
где η1 и η2 – показатели преломления двух сред, θ – угол падения, а θ’ – угол преломления (рис. 13). Обратите внимание что ни одно вёщество не пропускает весь падающий свет – часть его всегда отражается.
Рис. 13. Геометрия преломления
Как видно, учитывать эффекты преломления (даже направленного) достаточно сложно. Но если эту сложность преодолеть, то затраченное время с лихвой окупается чувством удовлетворения от полученных результатов. В простейшем случае прозрачные поверхности строятся отдельно от всех остальных, и в буфер записывается линейная комбинация двух ближайших поверхностей. При этом результирующая интенсивность рассчитывается по формуле
I = tI1+(1-t) I2 0≤t≤1
где I1 – видимая поверхность, I2 - поверхность, расположенная непосредственно за ней, t – коэффициент прозрачности I1.
Рис. 13. Учет эффекта прозрачности материала
Тени
Все согласятся, что изображение с тенями выглядит гораздо реалистичнее. Если положения наблюдателя и источника света совпадают, то теней не видно, но они появляются при перемещении наблюдателя в любую другую точку. Наблюдения и жизненный опыт подсказывают, что тень состоит из двух частей: полутени и полной тени. Полная тень – это центральная темная, резко очерченная часть, а полутень – окружающая ее более светлая часть. Распределенные источники света создают как тень, так и полутень. В полной тени свет вообще отсутствует, а полутень освещается частью распределенного источника. Сложность вычислений зависит от положения источника. Проще всего, когда источник находится в бесконечности, а тени определяются с помощью ортогонального проецирования. Сложнее если источник расположен на конечном расстоянии, но вне поля зрения, – здесь необходима перспективная проекция. И самый трудный случай – когда источник находится в поле зрения, ведь при этом необходимо делить пространство на секторы и искать тени отдельно для каждого из них. Все приведенные рассуждения легко распространить на несколько источников света. Очевидно, что при этом возрастает только сложность учета всех факторов.
Список литературы
1. Ю. Тихомиров. «Программирование трёхмерной графики». С.-Петербург БХВ-Петербург. 2001 г. (256 с.)
2. Роджерс Д. «Алгоритмические основы машинной графики». Пер. с англ. – Москва: Мир 1989 г. (512 с.)
3. Роджерс Д., Адамс Дж. «Математические основы машинной графики». Пер.с англ. – Москва: Машиностроение 1980 г. (240 с.)