Перейти к содержимому

Как работать с освещением на opengl

  • автор:

Использование источников света OpenGL для построения цветных теней

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

Должен сказать, что статья эта планировалась очень давно – года так с 2004, когда был написан трёхмерный движок, использующий описываемый метод. Однако, обилие формул и лень заставили меня уже в скором времени забросить написание статьи. Последний раз я касался текста в 2008 году. На этой дате статья и остановилась, и возрождать я её не планировал. Но недавно, в теме про исходники Quake 2, меня попросили всё же рассказать о применённой в моём трёхмерном движке технологии построения картинки. Актуальность столь запоздавших статей для современного программирования трёхмерной графики, конечно, нулевая, но возможно, начинающим изучать OpenGL эта статья будет интересна.

Для начала я покажу, какие именно получаются изображения при применении описываемого метода. Вот скриншоты моего движка 2004 года:

Скриншоты трёхмерного движка.

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

Идея алгоритма заключается в том, что многоугольник, источник тени (в дальнейшем – МИТ), своей тенью разбивает многоугольник, приёмник тени (в дальнейшем – МПТ) на фрагменты A, B, C, D, E, как показано на рисунке ниже. Можно заметить, что для фрагментов A, B, E, D источник света включён, а для фрагмента C источник света отключён

Разбиение на фрагменты тенью.

Общий алгоритм построения освещения таков:

  1. Выбираем источник света.
  2. Каждый многоугольник сцены разбиваем на фрагменты многоугольником, который может отбрасывать тень. При этом вновь получившиеся фрагменты будут являться новыми многоугольниками сцены, на которые нужно будет вновь построить тени от других многоугольников (но которые сами не будут источниками теней – бессмысленно использовать для построения тени части вместо исходного целого многоугольника). Такую операцию необходимо провести для всех многоугольников сцены.
  3. Переходим на шаг 1 для следующего источника света.

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

Как видите, метод несложный, однако, потребует алгоритма построения фрагментов, зная МИТ, МПТ и положение источника света.

Реализация алгоритма

Условимся считать все многоугольники выпуклыми. Есть это не так, их следует разбить на выпуклые части. Для реализации алгоритма нахождения фрагментов нам понадобятся некоторые функции, а именно:

Функция, определяющая позицию точки относительно некоторой плоскости.

Входные данные:

— Точка плоскости ;
— Вектор нормали к плоскости ;
— Точка, для которой определяется положение относительно плоскости .

Возвращаемое значение: 1 — точка находится выше плоскости, -1 — точка находится ниже плоскости, 0- точка находится в плоскости.

Для реализации этой функции воспользуемся уравнением плоскости, тогда (1).

Полученное определяет положение точки относительно плоскости.

Функция должна возвращать -1, если , возвращать 1, если и возвращать 0, если .

Однако, мы работаем на разрядной сетке ЭВМ, поэтому сравнивать с нулём нельзя. Вместо этого мы будем здесь и далее сравнивать с некоторым малым , значение которого проще всего подобрать опытным путём так, чтобы алгоритм не давал сбоев.

В этом случае функция должна возвращать -1, если , возвращать 1, если и возвращать 0 во всех остальных случаях.

Функция, определяющая точку пересечения прямой с плоскостью.

Входные данные:
— Точка плоскости ;
— Вектор нормали к плоскости ;
— Первая точка прямой ;
— Вторая точка прямой ;

Возвращаемое значение: координаты точки пересечения либо флаг, показывающий что пересечения нет.

Вектор , задающий направление прямой вычисляется как

Тогда скалярное произведение между вектором нормали и вектором прямой будет .

Если (в нашем случае это условие примет вид и ), то прямая и плоскость пересекаться не могут, поскольку вектора перпендикулярны.

Если же пересечение возможно, то координаты точки пересечения могут быть получены по формулам

где — значение, полученное по формуле (1).

Функция, определяющая точку пересечения луча с плоскостью.

Входные данные:

— Точка плоскости ;
— Вектор нормали к плоскости ;
— Первая точка луча (начало луча) ;
— Вторая точка луча .

Возвращаемое значение: координаты точки пересечения либо флаг, показывающий что пересечения нет.

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

Так, если получится, что для или для (в нашем случае для или для ), то луч плоскость не пересекает.

Функция, определяющая, нахождение точки внутри выпуклого многоугольника, лежащего в плоскости.

Входные данные:

— Точки многоугольника, лежащие в одной плоскости ;
— Точка, находящаяся в плоскости многоугольника, для которой проверяется её нахождение внутри многоугольника .

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

Алгоритм работы функции выглядит так:

Введём переменную =индекс последней точки многоугольника;
Цикл по от 0 до ;
Введём переменные индексов трёх последовательных точек ,,;
Если , то ;
Если , то ;
Возьмём три последовательные точки многоугольника ,,;
Создадим три вектора: по формулам

Вычислим векторные произведения и ;

Вычислим скалярное произведение ;
Если (в нашем случае ), то точка внутрь многоугольника не попадает.
Конец цикла;
Точка попадает внутрь многоугольника.

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

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

Алгоритм построения фрагментов

Входные данные:

— Точки выпуклого многоугольника, являющегося источником тени), лежащие в одной плоскости;
— Точки выпуклого многоугольника, на который отбрасывается тень), лежащие в одной плоскости;
-Точка положения источника света (далее по тексту ИС — «источник света»);

Возвращаемые данные: флаг, показывающий существует тень или нет, и массив многоугольников, на которые разбивается МПТ тенью.

Получение точек тени в плоскости МПТ

Рассмотрим алгоритм получения точек тени в системе координат МПТ.

    Проверим, что МИТ и МПТ имеют не менее трёх точек, иначе это, строго говоря, вообще не многоугольники, и тени нет.

Для этого сравним положение точки, точно попадающей в теневой объём относительно плоскостей, задаваемых гранями теневого объёма. Такая точка может быть получена, если найти геометрический центр МИТ
и пустить луч от ИС через этот центр, так же, как это делалось для нахождения вершин граней теневого объёма. Если при определении положения этой точки относительно плоскостей граней будет получено для какой-либо грани, что точка находится выше выбранной грани, то грань следует “перевернуть”, т.е. поменять знаки координат вектора нормали грани на противоположные. Направление обхода самих точек, задающих грань можно не менять, так как это в дальнейшем не понадобится.

Создание фрагмента

В архиве по ссылке (опять не на github — я с ним пока ещё не подружился) присутствуют программы с исходниками:

  1. Демонстрационная программа Lighting, строящая в реальном времени тени от двух источников света на пирамидку и плоскость под ней.
  2. 3D-движок, использующий вышеописанную технологию.
  3. Редактор карт 3D-движка (целиком на Win32API, никакого OWL или MFC).

Добавил ссылки на github:

OpenGL — Освещение и все что с ним связано

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

6.2 Модель освещения

По умолчанию освещение отключено. Включается оно командой glEnable(GL_LIGHTING). В базовом шаблоне освещение я включил, потому что без освещения работать практически невозможно. Сфера всегда будет показываться как круг, а конус — как круг или треугольник. Если монотонное тело у вас равномерно освещено, то вы не можете увидеть его рельеф. Поэтому нам нужно использовать источники света. Сначала рассмотрим функцию, которая устанавливает базовые настройки. Когда вы разрешили освещение, то вы можете уже устанавливать фоновую освещенность. По умолчанию, значение фоновой освещенности равно (0.2, 0.2, 0.2, 1). Создайте новый проект, скопируйте туда шаблонный файл и отключите освещение. Вы с трудом сможете различить сферу на экране. С помощью функции glLightModel вы можете установить фоновое освещение. Если вы повысите его до (1,1,1,1), т.е. до максимума, то включать источники света вам не понадобится. Вы их действия просто не заметите, т.к. объект уже максимально освещен. И получится, что вы как бы отключили освещение. В общем, добавьте в main вызов следующей функции:

float ambient[4] = ; . glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);

Попробуйте изменить параметры и посмотрите на результат. Нулевую лампу (glEnable(GL_LIGHT0)) лучше отключить.

Исходный файл смотрите здесь. Исполняемый файл здесь.

6.3 Материал

Материал может рассеивать, отражать и излучать свет. Свойства материала устанавливаются при помощи функции

glMaterialfv(GLenum face, GLenum pname, GLtype* params)

Первый параметр определяет грань, для которой устанавливаются свойства. Он может принимать одно из следующих значений:

GL_BACK задняя грань GL_FONT передняя грань GL_FRONT_AND_BACK обе грани

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

GL_AMBIENT рассеянный свет GL_DIFFUSE тоже рассеянный свет, пояснения смотри ниже GL_SPECULAR отраженный свет GL_EMISSION излучаемый свет GL_SHININESS степень отраженного света GL_AMBIENT_AND_DIFFUSE оба рассеянных света

Ambient и diffuse переводятся на русский как «рассеянный». Разница между ними не очень понятна. Я использую только GL_DIFFUSE. Третий параметр определяет цвет соответствующего света, кроме случая GL_SHININESS. Цвет задается в виде массива из четырех элементов — RGBA. В случае GL_SHININESS params указывает на число типа float, которое должно быть в диапазоне от 0 до 128. Я написал простенький пример с цилиндром и раскрасил его грани в разные цвета. Вам надо всего лишь модифицировать функцию display.

void CALLBACK display(void) < GLUquadricObj *quadObj; GLfloat front_color[] = ; GLfloat back_color[] = ; quadObj = gluNewQuadric(); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color); glMaterialfv(GL_BACK, GL_DIFFUSE, back_color); glPushMatrix(); glRotated(110, -1,1,0); gluCylinder(quadObj, 1, 0.5, 2, 10, 10); glPopMatrix(); gluDeleteQuadric(quadObj); auxSwapBuffers(); >

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

glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

Исходный файл смотрите здесь. Исполняемый файл здесь.

6.4 Лампы и их свойства

Все параметры лампы задаются с помощью функции glLight, которая имеет следующий прототип:

void glLight[if][v]( GLenum light, GLenum pname, GLfloat param)

Первый аргумент определяет номер лампы. Его можно задавать двумя способами. Первый — явно указать GL_LIHGTi, где GL_LIGHTi предопределено в файле gl.h следующим образом:

/* LightName */ #define GL_LIGHT0 0x4000 #define GL_LIGHT1 0x4001 #define GL_LIGHT2 0x4002 #define GL_LIGHT3 0x4003 #define GL_LIGHT4 0x4004 #define GL_LIGHT5 0x4005 #define GL_LIGHT6 0x4006 #define GL_LIGHT7 0x4007

Второй способ — GL_LIGHT0 + i, где i номер лампы. Такой способ используется, когда вам надо в цикле изменять параметры ламп. Второй аргумент определяет имя параметра, а третий его значение. Я здесь не буду перечислять всевозможные параметры и их допустимые значения, для этого есть справочник и MSDN. Я покажу и прокомментирую лишь небольшой пример, использующий три лампы. Для начала, давайте разберем шаблонный пример. С помощью следующих функций разрешаем освещение и включаем нулевую лампу.

glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);

Массивы pos и dir содержат координаты местоположения лампы и направления, куда она светит. Массив dir содержит три координаты — x,y,z. Массив pos — четыре, назначение четвертого мне не очень ясно. Если его значение отличается от нуля, то изображение вполне логичное получается. Если же он ноль, то получается что-то непотребное.

glLightfv(GL_LIGHT0, GL_POSITION, pos); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);

Создайте новый проект с именем lamps. Скопируйте шаблонный файл glaux.c. Отредактируйте функцию main:

void main() < float pos[4] = ; float color[4] = ; float sp[4] = ; float mat_specular[] = ; auxInitPosition( 50, 10, 400, 400); auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE ); auxInitWindow( "Glaux Template" ); auxIdleFunc(display); auxReshapeFunc(resize); glEnable(GL_DEPTH_TEST); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); glEnable(GL_LIGHT3); glEnable(GL_LIGHT5); glEnable(GL_LIGHT6); glLightfv(GL_LIGHT3, GL_SPECULAR, sp); glLightfv(GL_LIGHT5, GL_SPECULAR, sp); glLightfv(GL_LIGHT6, GL_SPECULAR, sp); color[1]=color[2]=0; glLightfv(GL_LIGHT3, GL_DIFFUSE, color); color[0]=0; color[1]=1; glLightfv(GL_LIGHT5, GL_DIFFUSE, color); color[1]=0; color[2]=1; glLightfv(GL_LIGHT6, GL_DIFFUSE, color); glLightfv(GL_LIGHT3, GL_POSITION, pos); pos[0] = -3; glLightfv(GL_LIGHT5, GL_POSITION, pos); pos[0]=0;pos[1]=-3; glLightfv(GL_LIGHT6, GL_POSITION, pos); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialf(GL_FRONT, GL_SHININESS, 128.0); auxMainLoop(display); >

Здесь надо сделать пояснения для вызовов функции glLight с параметрами GL_DIFFUSE и GL_SPECULAR. GL_DIFFUSE — определяет цвет света источника. В данном примере у нас три лампы — с красным источником света, с зеленым и с синим. GL_SPECULAR определяет отраженный свет, см. предыдущий пункт.

Теперь измените функцию display:

glColor3d(1,1,1); auxSolidSphere(2);

Исходный файл смотрите здесь. Исполняемый файл здесь.

6.5 Тени

Тени напрямую не поддерживаются библиотекой OpenGL, поэтому этот материал для второй части книги. А если честно, то я с ними пока еще не разбирался.;-)

Как работать с освещением на opengl

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

glEnable(GL_LIGHT0);

Остальные включаются аналогичным способом, где вместо GL_LIGHT0 указывается GL_LIGHTi. После того, как источник включен, необходимо задать его параметры. В OpenGL существует три типа источников света:

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

Для управления свойствами источника света используются команды glLight*:

glLightf(GLenum light, GLenum pname, GLfloat param);
glLightfv(GLenum light, GLenum pname, const GLfloat *param);

Параметр light указывает OpenGL для какого источника света задаются параметры. Команда glLightf используется для задания скалярных параметров, а glLightfv используется для задания векторных характеристик источников света.

Задание компонент излучения

Для источника света можно задать фоновую, рассеянную и зеркальную компоненты излучения.

Параметр pname команды glLightfv

Краткий комментарий

GL_AMBIENT
(0.0, 0.0, 0.0, 1.0)
GL_DIFFUSE
(1.0, 1.0, 1.0, 1.0) или (0.0, 0.0, 0.0, 1.0)
GL_SPECULAR
(1.0, 1.0, 1.0, 1.0) или (0.0, 0.0, 0.0, 1.0)

Остальные параметры являются специфическими для каждого типа источников света, описанных ниже.

Источники направленного света

Источника света такого типа находится в бесконечности и свет от него распространяется в заданном направлении. Идеально подходит для создания равномерного освещения. Хорошим примером источника направленного света может служить Солнце. У источника направленного света, кроме компонент излучения, можно задать только направление.

Параметр pname команды glLightfv

Краткий комментарий

GL_POSITION
(0.0, 0.0, 1.0, 0.0)

Первые три компоненты (x, y, z) задают вектор направления, а компонента w всегда равна нулю (иначе источник превратится в точечный).

Точечные источники света

Точечный источник света расположен в некоторой точке пространства и излучает во всех направлениях. Т.к. расстояние между источником и освещаемой точкой конечно, то можно задать закон убывания интенсивности излучения с расстоянием. Стандартные средства OpenGL позволяют задавать такой закон в виде обратно-квадратичной функции от расстояния:

f_<att></p>
<p>(d)=\frac + k_d + k_d^2>» /></p>
<p>Т.о. для точечного источника света, кроме свойств излучения, можно задать ещё четыре параметра:</p>
<p><b>Параметр <em>pname</em> команды <strong>glLightfv</strong></b></p>
<p><strong>Краткий комментарий</strong></p>
<pre>GL_POSITION</pre>
<pre>(0.0, 0.0, 1.0, 0.0)</pre>
<pre>GL_CONSTANT_ATTENUATION</pre>
<pre>GL_LINEAR_ATTENUATION</pre>
<pre>GL_QUADRATIC_ATTENUATION</pre>
<p>Как видно из таблицы, по умолчанию, интенсивность света не убывает с расстоянием.</p>
<p>Прим. Позиция источника света (в случае направленного источника — направление) задается в <strong>текущей</strong> <strong>модельной системе координат.</strong> Например, после выполнения кода:</p>
<p>glPushMatrix(); <br />glLoadIdentity(); <br />glTranslatef(1.0, 1.0, 1.0); <br />GLfloat light0_position[] = < 0.0, 0.0, 0.0, 1.0 >; <br />glLightfv(GL_LIGHT0, GL_POSITION, light0_position); <br />glPopMatrix();</p>
<p>нулевой источник света будет расположен в точке (1.0, 1.0, 1.0) во внешней (мировой) системе координат.</p>
<h5>Прожекторы</h5>
<p>Одной из разновидностей точечного источника является прожектор. Для него применимы все параметры, что и для точечного источника, но кроме того прожектор позволяет ограничить распространение света конусом. Для этого конуса можно задать коэффициент убывания интенсивности, в зависимости от угла между осью конуса и лучом распространения света.</p>
<p> <img decoding=

Параметры, специфические для прожектора:

Параметр pname команды glLightfv

Краткий комментарий

Освещение в OpenGL

Освещение какого-либо пространства — это процесс, благодаря которому это пространство наполняется светом и все находящиеся в нём предметы делаются видимыми.
Освещение любого объекта зависит от двух факторов:

  • Первый — это материал, из которого сделан объект.
  • Второй — это свет, которым он освещен.

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

  • glEnable(GL_LIGHT0);

Остальные включаются аналогичным способом, где вместо GL_LIGHT0 указывается GL_LIGHTi. После того, как источник включен, необходимо задать его параметры. Если монотонное тело у вас равномерно освещено, то вы не можете увидеть его рельеф. Поэтому нам нужно использовать источники света.
В OpenGL существует три типа источников света:

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

Для управления свойствами источника света используются команды glLight*:

  • glLightf(GLenum light, GLenum pname, GLfloat param);
    glLightfv(GLenum light, GLenum pname, const GLfloat *param);

Параметр light указывает OpenGL для какого источника света задаются параметры. Команда glLightf используется для задания скалярных параметров, а glLightfv используется для задания векторных характеристик источников света.

Сначала рассмотрим функцию, которая устанавливает базовые настройки. Когда вы разрешили освещение, то вы можете уже устанавливать фоновую освещенность. По умолчанию, значение фоновой освещенности равно (0.2, 0.2, 0.2, 1). Создайте новый проект, скопируйте туда шаблонный файл и отключите освещение. Вы с трудом сможете различить сферу на экране. С помощью функции glLightModel вы можете установить фоновое освещение. Если вы повысите его до (1,1,1,1), т.е. до максимума, то включать источники света вам не понадобится. Вы их действия просто не заметите, т.к. объект уже максимально освещен. И получится, что вы как бы отключили освещение. В общем, добавьте в main вызов следующей функции:

  • float ambient[4] = ;
    .
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);

Попробуйте изменить параметры и посмотрите на результат.

Материал
Материал может рассеивать, отражать и излучать свет. Свойства материала устанавливаются при помощи функции

  • glMaterialfv(GLenum face, GLenum pname, GLtype* params)

Первый параметр определяет грань, для которой устанавливаются свойства. Он может принимать одно из следующих значений:

  • GL_BACK задняя грань
    GL_FONT передняя грань
    GL_FRONT_AND_BACK обе грани

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

  • GL_AMBIENT рассеянный свет
    GL_DIFFUSE тоже рассеянный свет
    GL_SPECULAR отраженный свет
    GL_EMISSION излучаемый свет
    GL_SHININESS степень отраженного света
    GL_AMBIENT_AND_DIFFUSE оба рассеянных света

Цвет задается в виде массива из четырех элементов — RGBA. В случае GL_SHININESS params указывает на число типа float, которое должно быть в диапазоне от 0 до 128.
Вам надо всего лишь модифицировать функцию display.

  • void CALLBACK display(void)
    GLUquadricObj *quadObj;
    GLfloat front_color[] = ;
    GLfloat back_color[] = ;
    quadObj = gluNewQuadric();
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);
    glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);
    glPushMatrix();
    glRotated(110, -1,1,0);
    gluCylinder(quadObj, 1, 0.5, 2, 10, 10);
    glPopMatrix();
    gluDeleteQuadric(quadObj);
    auxSwapBuffers();
    >

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

  • glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);

Источники направленного света
Источника света такого типа находится в бесконечности и свет от него распространяется в заданном направлении. Идеально подходит для создания равномерного освещения. Хорошим примером источника направленного света может служить Солнце. У источника направленного света, кроме компонент излучения, можно задать только направление.

  • GL_POSITION (0.0, 0.0, 1.0, 0.0) //(x, y, z, w) направление источника направленного света

Первые три компоненты (x, y, z) задают вектор направления, а компонента w всегда равна нулю (иначе источник превратится в точечный).

Функции затухания
Это функция изменения интенсивности освещения(интенсивность света не убывает с расстоянием) , используется вместе с точечным освещением

  • GL_POSITION(0.0, 0.0, 1.0, 0.0)//позиция источника света (по умолчанию источник света направленный)
  • GL_CONSTANT_ATTENUATION 1.0 //постоянная k_const в функции затухания f(d)
  • GL_LINEAR_ATTENUATION 0.0 //коэффициент k_linear при линейном члене в функции затухания f(d)
  • GL_QUADRATIC_ATTENUATION 0.0 //коэффициент k_quadratic при квадрате расстояния в функции затухания f(d)

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

  • GL_SPOT_DIRECTION (0.0, 0.0, -1.0) //(x, y, z) — направление прожектора (ось ограничивающего конуса)
  • GL_SPOT_CUTOFF 180.0 //угол между осью и стороной конуса (он же половина угла при вершине)
  • GL_SPOT_EXPONENT 0.0 //экспонента убывания интенсивности

Тени
Тени напрямую не поддерживаются библиотекой OpenGL, поэтому их нужно разбирать отдельно .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *