Автор работы: Пользователь скрыл имя, 16 Апреля 2013 в 17:23, реферат
После того, как задана необходимая геометрия (нормали) необходимо разместить на сцене один или несколько источников света, настроить их свойства и включить их. В зависимости от реализации OpenGL на сцене могут присутствовать восемь и более источников света. Включить нулевой источник света можно командой:
glEnable(GL_LIGHT0);
Источники света
После того, как задана необходимая геометрия (нормали) необходимо разместить на сцене один или несколько источников света, настроить их свойства и включить их. В зависимости от реализации 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_LIGHT0 - белый, для остальных - черный) |
GL_SPECULAR |
(1.0, 1.0, 1.0, 1.0) или (0.0, 0.0, 0.0, 1.0) |
цвет зеркального излучения источника света (значение по умолчанию для GL_LIGHT0 - белый, для остальных - черный) |
Остальные параметры являются специфическими для каждого типа источников света, описанных ниже.
Источники направленного света
Источника света такого типа находится в бесконечности и свет от него распространяется в заданном направлении. Идеально подходит для создания равномерного освещения. Хорошим примером источника направленного света может служить Солнце. У источника направленного света, кроме компонент излучения, можно задать только направление.
Параметр pname команды glLightfv | ||
Имя параметра |
Значение по умолчанию |
Краткий комментарий |
GL_POSITION |
(0.0, 0.0, 1.0, 0.0) |
(x, y, z, w) направление источника направленного света |
Первые три компоненты (x, y, z) задают вектор направления, а компонента w всегда равна нулю (иначе источник превратится в точечный).
Точечные источники света
Точечный источник света расположен в некоторой точке пространства и излучает во всех направлениях. Т.к. расстояние между источником и освещаемой точкой конечно, то можно задать закон убывания интенсивности излучения с расстоянием. Стандартные средства OpenGL позволяют задавать такой закон в виде обратно-квадратичной функции от расстояния:
Т.о. для точечного источника света, кроме свойств излучения, можно задать ещё четыре параметра:
Параметр pname команды glLightfv | ||
Имя параметра |
Значение по умолчанию |
Краткий комментарий |
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) |
Как видно из таблицы, по умолчанию, интенсивность света не убывает с расстоянием.
Прим. Позиция источника света (в случае направленного источника - направление) задается в текущей модельной системе координат. Например, после выполнения кода:
glPushMatrix();
glLoadIdentity();
glTranslatef(1.0, 1.0, 1.0);
GLfloat light0_position[] = { 0.0, 0.0, 0.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glPopMatrix();
нулевой источник света будет расположен в точке (1.0, 1.0, 1.0) во внешней (мировой) системе координат.
Прожекторы
Одной из разновидностей точечного источника является прожектор. Для него применимы все параметры, что и для точечного источника, но кроме того прожектор позволяет ограничить распространение света конусом. Для этого конуса можно задать коэффициент убывания интенсивности, в зависимости от угла между осью конуса и лучом распространения света.
Параметры, специфические для прожектора:
Параметр pname команды glLightfv | ||
Имя параметра |
Значение по умолчанию |
Краткий комментарий |
GL_SPOT_DIRECTION |
(0.0, 0.0, -1.0) |
(x, y, z) - направление прожектора (ось ограничивающего конуса) |
GL_SPOT_CUTOFF |
180.0 |
угол между осью и стороной конуса (он же половина угла при вершине) |
GL_SPOT_EXPONENT |
0.0 |
экспонента убывания интенсивности |
Пример кода
#include <GL/glut.h>
#include <math.h>
#define PI 3.141592653
int light_sample = 1;
// инициализация
void init (void)
{
// цвет фона
glClearColor (0.3, 0.3, 0.3, 0.0);
// рассчет освещения
glEnable(GL_LIGHTING);
// двухсторонний расчет освещения
glLightModelf(GL_LIGHT_MODEL_
// автоматическое приведение нормалей к
// единичной длине
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 display(void)
{
// очищаем буфер кадра и глубины
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// свойства материала
GLfloat material_diffuse[] = {1.0, 1.0, 1.0, 1.0};
glMaterialfv(GL_FRONT_AND_
// установка источников света
if (light_sample == 1)
{
// направленный источник света
GLfloat light0_diffuse[] = {0.4, 0.7, 0.2};
GLfloat 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);
}
if (light_sample == 2)
{
// точечный источник света
// убывание интенсивности с расстоянием
// отключено (по умолчанию)
GLfloat light1_diffuse[] = {0.4, 0.7, 0.2};
GLfloat light1_position[] = {0.0, 0.0, 1.0, 1.0};
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
}
if (light_sample == 3)
{
// точечный источник света
// убывание интенсивности с расстоянием
// задано функцией f(d) = 1.0 / (0.4 * d * d + 0.2 * d)
GLfloat light2_diffuse[] = {0.4, 0.7, 0.2};
GLfloat light2_position[] = {0.0, 0.0, 1.0, 1.0};
glEnable(GL_LIGHT2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_diffuse);
glLightfv(GL_LIGHT2, GL_POSITION, light2_position);
glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, 0.2);
glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.4);
}
if (light_sample == 4)
{
// прожектор
// убывание интенсивности с расстоянием
// отключено (по умолчанию)
// половина угла при вершине 30 градусов
// направление на центр плоскости
GLfloat light3_diffuse[] = {0.4, 0.7, 0.2};
GLfloat light3_position[] = {0.0, 0.0, 1.0, 1.0};
GLfloat light3_spot_direction[] = {0.0, 0.0, -1.0};
glEnable(GL_LIGHT3);
glLightfv(GL_LIGHT3, GL_DIFFUSE, light3_diffuse);
glLightfv(GL_LIGHT3, GL_POSITION, light3_position);
glLightf(GL_LIGHT3, GL_SPOT_CUTOFF, 30);
glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, light3_spot_direction);
}
if (light_sample == 5)
{
// прожектор
// убывание интенсивности с расстоянием
// отключено (по умолчанию)
// половина угла при вершине 30 градусов
// направление на центр плоскости
// включен рассчет убывания интенсивности для прожектора
GLfloat light4_diffuse[] = {0.4, 0.7, 0.2};
GLfloat light4_position[] = {0.0, 0.0, 1.0, 1.0};
GLfloat light4_spot_direction[] = {0.0, 0.0, -1.0};
glEnable(GL_LIGHT4);
glLightfv(GL_LIGHT4, GL_DIFFUSE, light4_diffuse);
glLightfv(GL_LIGHT4, GL_POSITION, light4_position);
glLightf(GL_LIGHT4, GL_SPOT_CUTOFF, 30);
glLightfv(GL_LIGHT4, GL_SPOT_DIRECTION, light4_spot_direction);
glLightf(GL_LIGHT4, GL_SPOT_EXPONENT, 15.0);
}
if (light_sample == 6)
{
// несколько источников света
GLfloat light5_diffuse[] = {1.0, 0.0, 0.0};
GLfloat light5_position[] = {0.5 * cos(0.0), 0.5 * sin(0.0), 1.0, 1.0};
glEnable(GL_LIGHT5);
glLightfv(GL_LIGHT5, GL_DIFFUSE, light5_diffuse);
glLightfv(GL_LIGHT5, GL_POSITION, light5_position);
glLightf(GL_LIGHT5, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(GL_LIGHT5, GL_LINEAR_ATTENUATION, 0.4);
glLightf(GL_LIGHT5, GL_QUADRATIC_ATTENUATION, 0.8);
GLfloat light6_diffuse[] = {0.0, 1.0, 0.0};
GLfloat light6_position[] = {0.5 * cos(2 * PI / 3), 0.5 * sin(2 * PI / 3), 1.0, 1.0};
glEnable(GL_LIGHT6);
glLightfv(GL_LIGHT6, GL_DIFFUSE, light6_diffuse);
glLightfv(GL_LIGHT6, GL_POSITION, light6_position);
glLightf(GL_LIGHT6, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(GL_LIGHT6, GL_LINEAR_ATTENUATION, 0.4);
glLightf(GL_LIGHT6, GL_QUADRATIC_ATTENUATION, 0.8);
GLfloat light7_diffuse[] = {0.0, 0.0, 1.0};
GLfloat light7_position[] = {0.5 * cos(4 * PI / 3), 0.5 * sin(4 * PI / 3), 1.0, 1.0};
glEnable(GL_LIGHT7);
glLightfv(GL_LIGHT7, GL_DIFFUSE, light7_diffuse);
glLightfv(GL_LIGHT7, GL_POSITION, light7_position);
glLightf(GL_LIGHT7, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(GL_LIGHT7, GL_LINEAR_ATTENUATION, 0.4);
glLightf(GL_LIGHT7, GL_QUADRATIC_ATTENUATION, 0.8);
}
// плоскость
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);
glDisable(GL_LIGHT1);
glDisable(GL_LIGHT2);
glDisable(GL_LIGHT3);
glDisable(GL_LIGHT4);
glDisable(GL_LIGHT5);
glDisable(GL_LIGHT6);
glDisable(GL_LIGHT7);
// элемент двойной буферизации
glutSwapBuffers();
}
void keyboard_function(unsigned char key, int x, int y)
{
if (key == '1') light_sample = 1;
if (key == '2') light_sample = 2;
if (key == '3') light_sample = 3;
if (key == '4') light_sample = 4;
if (key == '5') light_sample = 5;
if (key == '6') light_sample = 6;
glutPostRedisplay();
}
void main (int argc, char** argv)
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition (50, 100);
glutInitWindowSize (500, 500);
glutCreateWindow ("4.4. Пример установки источников света в OpenGL. (с) compgraphics.info");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard_
glutMainLoop ();
}