Внимание!

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

Основы освещения в OpenGL

Урок 2. Основы освещения в OpenGL
Ну вот наконец-то и пришел 2 урок =). Задержался он немного, так как были проблемы с жестким диском и с инетом. Но вот вышел второй урок =). В этом уроке я раскажу про освещение.

[spoiler]

Часть 1. Подготавливаемся

Что нам нужно для того, чтобы изучать освещение? Нам нужны:
- OpenGL(как же без него);
- glut;
- IDE (хотя можно и без него, я, например, пишу все свои программы в gedit (что то вроде блокнота на винде только круче), иногда в CodeBlocks (ну это только если проект большой, чтобы легче было) );
- ну и конечно нужен компилятор (как же без него), я использую компилятор gcc для Linux и mingw для Windows;
- и еще очень пригодится желание учиться (без него никак).


Часть 2. Пример простой программы


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

/*http://esate.ru, isaer*/

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

void init()
{
   glClearColor(0.3, 0.3, 0.3, 1.0);
   glEnable(GL_LIGHTING);
   glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
   glEnable(GL_NORMALIZE);
}

void reshape(int width, int height)
{
   glViewport(0, 0, width, height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   
   glOrtho(-1.2, 1.2, -1.2, 1.2, -1, 1);
   
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void init_l()
{
   float light0_diffuse[] = {0.4, 0.7, 0.2};
   float light0_direction[] = {0.0, 0.0, 1.0, 0.0};

   glEnable(GL_LIGHT0);

   glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
   glLightfv(GL_LIGHT0, GL_POSITION, light0_direction);
}

void display()
{
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   init_l();
    
   GLfloat x, y;
   glBegin(GL_QUADS);
   glNormal3f(0.0, 0.0, -1.0);
   for (x = -1.0; x < 1.0; x += 0.005)
   {
  for (y = -1.0; y < 1.0; y += 0.005)           
  {
     glVertex3f(x, y, 0.0);
        glVertex3f(x, y + 0.005, 0.0);
        glVertex3f(x + 0.005, y + 0.005, 0.0);
        glVertex3f(x + 0.005, y, 0.0);
       }
    }
   glEnd();
   
   glDisable(GL_LIGHT0);
   glutSwapBuffers();
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowPosition(50, 100);
   glutInitWindowSize(500, 500);
   glutCreateWindow("Light");
   init();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutMainLoop();
}


Код без коментариев так что то бы понять суть освещения нодо читать дальше =)

Часть 3. Небольшой разбор примера

Начнем разирать код примера.
Я все не буду пояснять, так как почти все есть в предыдушем уроке.

/*http://esate.ru, isaer*/

void init()
{
   glClearColor(0.3, 0.3, 0.3, 1.0);
   glEnable(GL_LIGHTING);
   glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
   glEnable(GL_NORMALIZE);
}


Тут мы инициализируем всякое =)

glClearColor(0.3, 0.3, 0.3, 1.0); //очищаем экран в цвет, установленый параметрами r,g,b,a
glEnable(GL_LIGHTING); //тут мы включаем расчет освещения
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);//делаем так, чтобы освещались обе стороны полигона
glEnable(GL_NORMALIZE);//делам нормали одинаковой величины во избежание артефактов


/*http://esate.ru, isaer*/

void init_l()
{
   float light0_diffuse[] = {0.4, 0.7, 0.2};
   float light0_direction[] = {0.0, 0.0, 1.0, 0.0};

   glEnable(GL_LIGHT0);

   glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
   glLightfv(GL_LIGHT0, GL_POSITION, light0_direction);
}


Здесь инициализируется освещение.

float light0_diffuse[] = {0.4, 0.7, 0.2};//устанавливаем диффузный цвет света
float light0_direction[] = {0.0, 0.0, 1.0, 0.0};//устанавливаем направление света
glEnable(GL_LIGHT0);//разрешаем использовать light0
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);//устанавливаем источнику света light0 диффузный свет, который указали ранее
glLightfv(GL_LIGHT0, GL_POSITION, light0_direction);//устанавливаем направление источника света указанным ранее

/*http://esate.ru, isaer*/

void display()
{
   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   init_l();
    
   GLfloat x, y;
   glBegin(GL_QUADS);
   glNormal3f(0.0, 0.0, -1.0);
   for (x = -1.0; x < 1.0; x += 0.005)
   {
  for (y = -1.0; y < 1.0; y += 0.005)           
  {
        glVertex3f(x, y, 0.0);
        glVertex3f(x, y + 0.005, 0.0);
        glVertex3f(x + 0.005, y + 0.005, 0.0);
        glVertex3f(x + 0.005, y, 0.0);
       }
   }
   glEnd();
   
   glDisable(GL_LIGHT0);
   glutSwapBuffers();
}



Здесь происходит вся прорисовка.

init_l();//выполняем инициализацию освещения
GLfloat x, y;//высота и ширина плоскости
glBegin(GL_QUADS);//начинаем рисовать плоскость
glNormal3f(0.0, 0.0, -1.0);//указываем направление нормалей (это обязательно)
//тут рисуем плоскость
glEnd();//закончили рисовать
glDisable(GL_LIGHT0);//отключаем освещение

Ну, вот вроде с примером разобрались. Далее будем изучать освещение.


Часть 4. Изучаем освещение

Вначале включим расчет освещения командой glEnable(GL_LIGHTING);
далее надо разблокировать источник света командой glEnable(GL_LIGHT);
GL_LIGHT может принимать только 8 значений (по крайней мере в OpenGL 2.1, как и у меня), то есть GL_LIGHT0..GL_LIGHT7.

Теперь надо создать источник света. У каждого источника света есть свои параметры по умолчанию, например, если вы просто разблокируете 2 источника света GL_LIGHT0 и GL_LIGHT1, то будет виден только 0, так как в нем параметры по умолчанию отличаються от остальных (у всех остальных они идентичны).

Источники света имеют несколько параметров, таких как: цвет, позиция и направление.
Команда, используемая для указания всех параметров света – это glLight*(). Она принимает три аргумента: идентификатор источника света, имя свойства и желаемое для него значение.

/*http://esate.ru, isaer*/

void glLight{if} (GLenum light, GLenum pname, TYPE param);
void glLight{if}v (GLenum light, GLenum pname, TYPE *param);


GLenum light - это выбор источника, например, GL_LIGHT0
GLenum pname - это параметры источника света (далее будут приведены все ее параметры)
TYPE param - это значение, которое принимает GLenum pname

Если у вас стоит void glLight{if}v (GLenum light, GLenum pname, TYPE *param), значит используется векторная версия команды; param представляет собой вектор величин.

Например:

/*http://esate.ru, isaer*/

float light_ambient[] = {0.0,0.0,0.0,1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);


Или, если нет, то тогда это единственное значение.

Например:

/*http://esate.ru, isaer*/

glLightf(GL_LIGHT0, GL_GL_SPOT_CUTOFF, 180);


Вот листинг значений GLenum pname
(читаеться так: первая строчка - это название параметра, вторая - это значение поумолчанию и третья - это пояснение; если вы видите что-то типа (1.0,1.0,1.0,1.0) или (0.0,0.0,0.0,1.0), то это значит, что первая скобка - это значение по умолчанию для нулевого источника, а вторая скобка - это для остальных):

/*http://esate.ru, isaer*/

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)
Интенсивность диффузного света (значение по умолчанию 
для 0-го источника - белый свет, для остальных - черный)

GL_SPECULAR
(1.0,1.0,1.0,1.0)
или
(0.0,0.0,0.0,1.0)
Интенсивность зеркального света (значение по умолчанию для 0-го источника - белый свет, для остальных - черный)

GL_POSITION
(0.0,0.0,1.0,0.0)
Положение источника света (x,y,z,w)

GL_SPOT_DIRECTION
(0.0,0.0,-1.0)
Направление света прожектора (x,y,z)

GL_SPOT_EXPONENT
0.0
Концентрация светового луча

GL_SPOT_CUTOFF
180.0
Угловая ширина светового луча

GL_CONSTANT_ATTENUATION
1.0
Постоянный фактор ослабления

GL_LINEAR_ATTENUATION
0.0
Линейный фактор ослабления

GL_QUADRATIC_ATTENUATION
0.0
Квадратичный фактор ослабления

вот пример использования освещения:
/*http://esate.ru, isaer*/

float light_ambient[] = {0.0,0.0,0.0,1.0};
float light_diffuse[] = {1.0,1.0,1.0,1.0};
float light_specular[] = {1.0,1.0,1.0,1.0};
float light_position[] = {1.0,1.0,1.0,0.0};

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);


Часть 5. Изучаем параметры света

1.Цвет

Diffuse
Параметр GL_DIFFUSE, наверное, наиболее точно совпадает с тем, что вы привыкли называть «цветом света». Он определяет RGBA цвет диффузного света, который отдельный источник света добавляет к сцене.

Ambient
Параметр GL_AMBIENT влияет на цвет зеркального блика на объекте. В реальном мире на объектах вроде стеклянной бутылки имеется зеркальный блик соответствующего освещению цвета (часто белого).

Specular
Параметр GL_SPECULAR влияет на интенсивность зеркального блика на объектах.

2.Позиция

Position
Параметр GL_POSITION имеет 3 значения положения и одно, указывающее на то, какой источник света будет использоваться.
GL_POSITION (x,y,z,w)
Первые 3 параметра понятны - это положение, а вот 4-й параметр указывает, будет ли использоваться бесконечно удаленный свет или точечный. Если значение w = 0, то источник света бесконечно удаленный (что-то вроде солнца). Если w = 1, то этот источник света точечный (что то вроде лампочки).
Если w = 0, то первые 3 параметра - это вектор от центра системы координат (0,0,0).

3.Прожектор

GL_SPOT_DIRECTION
Направление света прожектора

GL_SPOT_EXPONENT
Концентрация светового луча

GL_SPOT_CUTOFF
Угловая ширина светового луча

Я думаю тут все понятно, единственное, нужно уточнить, что позиция должна быть с w = 1.

4.Ослабление


Если вам нужно ослаблять интенсивность света от центра(тоесть чем дальше от центра, тем тускнее), то вам надо настроить параметры: GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION.

Но так не удобно и можно расчитать по формуле:

/*http://esate.ru, isaer*/

Fatt = 1 / (Kc + Kl * d + Kq  * (d * d))


где:
d - расстояние между позицией источника света и точкой где конец,
Kc - GL_CONSTANT_ATTENUATION (постоянный фактор ослабления),
Kl - GL_LINEAR_ATTENUATION (линейный фактор ослабления),
Kq - GL_QUADRATIC_ATTENUATION (квадратичный фактор ослабления).

Если вы не совсем поняли, как это применить, то у меня уже есть готовая заготовка:

/*http://esate.ru, isaer*/

  
float kQ;
float kL;
float kC;
float radius;
float att;

attn = 1;
radius = 5;
kQ = att / (3* radius * radius);
kL = att / (3 * radius);
kC = att / 3; 

glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, kC);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, kL);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, kQ);


Тут вы задаете радиус от центра до конца =)
Также, если вам надо уменьшить общую интенсивность, вы можете изменить параметр att


Часть 6. Выбор модели освещения

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

glLightModel*() – это команда, используемая для задания всех параметров модели освещения. glLightModel*() принимает два аргумента: имя параметра модели освещения в виде константы и значение для этого параметра.

/*http://esate.ru, isaer*/

void glLightModel{if} (GLenum pname, TYPE param);
void glLightModel{if}v (GLenum pname, TYPE *param); 


Устанавливаемая характеристика модели освещения определяется аргументом pname; param задает величину, в которую устанавливается pname.

/*http://esate.ru, isaer*/

GL_LIGHT_MODEL_AMBIENT
(0.2,0.2,0.2,1.0)
RGBA интенсивность всей сцены

GL_LIGHT_MODEL_LOCAL_VIEWER
0.0 или GL_FALSE
способ вычисления углов зеркального отражения

GL_LIGHT_MODEL_TWO_SIDE
0.0 или GL_FALSE
выбор между односторонним и двухсторонним освещением

GL_LIGHT_MODEL_COLOR_CONTROL
GL_SINGLE_COLOR
вычисляется ли зеркальный цвет отдельно от фонового и диффузного

Часть 7. Заключение

Ну вот и все, с освещением закончили =)
Теперь вы можете создавать отличные источники света.

Вот тут есть отличный пример использования всех источников света, найденый мною в недрах интернета.
Lesson2_Light(Linux, Windows).
В архиве лежит исходный код программы (мною подредактированый) и исполняемые файлы под Linux и под Windows.


Также, если вы компилируете под Windows с помощю компилятора mingw, то там компиляция немного отличается.Надо писать:

/*http://esate.ru, isaer*/

i586-mingw32msvc-g++ file.cpp -lopengl32 -lglu32 -lglut32win -o file.exe


Также вам надо будет скачать библиотеку glut для mingw (в гугле есть точно),
а если под линукс с помощью gcc, то там как обычно:
/*http://esate.ru, isaer*/

g++ file.cpp -lglut -lGLU -o file
0      3022        25.08.2010        21

Внимание!

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

0 
25.08.2010 00:00:00
понравилась статья? поставь плюс =))
0 
26.08.2010 00:00:00
Отлично)
0 
26.08.2010 00:00:00
По-моему статья отличная — достаточно информативная!
Только код без комментариев меня немного смутил :) Все таки не для профи пишем, а для людей, которым что-то не ясно, которые разобраться хотят (имхо).
0 
26.08.2010 00:00:00
я вроде все коментировал
там вначале пример весь закоментирован
да и дальше почти каждую строчку пояснял

если что не так то напиши что исправить я подправлю
0 
26.08.2010 00:00:00
У тебя все классно получилось!
Просто в самом коде комментов нет и если кто-то очень ленивый вначале копи-пастит, а потом только разбираться начинает, то туго ему бедненькому придется :)
Хотя это уже его проблемы мы для лентяев не стараемся :)))

Кстати по-поводу лентяев, а у тебя есть такой же код только на C#? :)))
0 
26.08.2010 00:00:00
нет на шарп нету
так а там изменять почти ничего не надо
только перед gl ставить GL. и все (вроде)
я на шарпе уже давно не программировал
так как мне больше С++ понравился =)
хотя так скучаю по формачкам и кнопочкам =)
0 
26.08.2010 00:00:00
«только перед gl ставить GL. и все (вроде)»Вот-вот я про лентяев и говорю :)))
Там перед каждым из параметров внутри функции например glutInitDisplayMode(...) или др. нужно Gl. ставить. Ну ни чего, блокнот мне в руки ;)
0 
26.08.2010 00:00:00
=)
ты скачай пример, там класно =) мне понравился
правда я там убрал один прикол
а зря, с ним лучше было, ты просто делай так:
напиши в первой строчке GL. и скопируй ее и потом просто везде Ctrl + V
ну и на стрклочках строчку ниже и Home чт бы в начало строчки

там быстро тогда
0 
26.08.2010 00:00:00
ах да я же забыл =)) там если на форму делать то надо менять код (и давольнотаки много)
ты сделай на консоле, почти ничего не надо

и вобще чет меня занесло, может ты не про пример тот говоришь =))
там просто есть исполняемый файл для винды и для линукса
0 
27.08.2010 00:00:00
Все нормально, я сам код по созданию освещения перенесу на Шарп в ВинФормс и посмотрю как работает, а потом если вопросы появятся, опять сюда и буду спрашивать ;)))

Кстати, если захочешь, когда код будет готов я могу тебе скинуть (или сразу Anvi), чтобы он в конце урока ссылку на C#+TaoFramework проект сделал. Мало ли, вдруг людям пригодится :)
0 
28.08.2010 00:00:00
кидай anvi пусть он льет, меня просто может долго не быть
0 
29.08.2010 00:00:00
Перенес в «Новые уроки OpenGL». Это можно сделать и самостоятельно, имея соответствующий рейтинг (по моему, если не подводит память ~0.8)

Еще, просьба ко всем, кто создает новые уроки, к урокам. Это поможет не упустить несколько важных вещей для создания качественных, полных уроков.
0 
01.02.2011 00:00:00
А его сразу не нашел, извиняюсь, что требовал продолжения первого урока, когда нужно было просить продолжения второго)))
0 
01.02.2011 00:00:00
все собираюсь сделать про текстурирование
0 
01.02.2011 00:00:00
Еще один классный урок!!! Я его тоже раньше не находил.(
Ща попробую в mingw, а то у меня OGl там не компилился. После чего, я mingw и забросил.
Побольше бы Linux-а в нашу жизнь!;)))
0 
01.02.2011 00:00:00
Linux — крут =)

может быть когда нить сделаю что нить по типу блога про линукс =) там как компилировать в разных средах, как подключать файлы, Makefiles
сейчас просто времени не очень много
но вскоре думаю сделаю
0 
01.02.2011 00:00:00
Вот только жаль что вы не находили раньше, надо как то навигацию поправить на сайте, а то я свои топики с трудом нахожу
0 
01.02.2011 00:00:00
Это надо=)
0 
01.02.2011 00:00:00
Linux — это сила!)
может быть когда нить сделаю что нить по типу блога про линукс =)Это очень классно.
Буду надеяться на то, что времени у тебя станет побольше.))
Ну и у меня заодно)))
0 
02.02.2011 00:00:00
люди
вот смотрю я тут и не могу понять к чему эти разные приставки например
m_Surface — что означает эта m_ ??
и какие еще приставки знаете? а то я как то все называю без приставок, может если кто читает и ему будет с приставками понятнее
0 
07.03.2011 00:00:00
Отношение к кому-то классу или объект наверное, ну как сделаешь, чтоб не путать добавляй.
^
Регистрация
Регистрируясь, вы принимаете правила сайта. Если вы не получили код подтв. регистрации - не забудьте проверить папку спам.
Логин*
Email*
Пароль*
Подтверждение пароля*
 
Логин*
Код*
 
×
Восстановление пароля
Пожалуйста, заполните поля, после чего вы получите код подтверждения на ваш Email. Если код не пришел в течении нескольких минут - проверьте папку спам.
Логин

или Email
Логин*
Код подтверждения*
Новый пароль*
Подтверждение пароля*
×
Авторизация
  • Используйте вашу учетную запись на Facebook.com для входа на сайт.
  • Используйте вашу учетную запись VKontakte для входа на сайт.
  • Используйте вашу учетную запись Google для входа на сайт.
Авторизуйтесь с помощью соц. сети или с помощью аккаунта на сайте:
×