Цель лекции: Изучить команды OpenGL включения и отключения источников света, изменения свойств материала примитивов, роль нормалей в освещении примитивов, а также реализацию этих команд на Object Pascal и в библиотеке OpenTK на C#.
Пример № 6.1 Пример демонстрирует освещение примитивов без указания направления нормалей.
Пример № 6.2 Пример демонстрирует освещение примитивов c указанием направления нормалей.
Одним из элементов создания реалистичных изображений является освещение объектов. Освещение объектов в OpenGL неразрывно связано со свойствами источников света и свойствами материала примитивов.
По умолчанию в библиотеке OpenGL режим освещения отключен. В этой ситуации цвет отображаемых объектов задается с помощью команды Color (см. раздел 3.4). Включение и выключение режима освещения осуществляется с помощью команд Enable и Disable с параметром:
C#: EnableCap.Lighting Object Pascal: GL_LIGHTING
Включить и выключить режим освещения можно в любой момент после инициализации библиотеки OpenGL.
Для того чтобы объекты были освещены необходимо кроме включения режима освещения, также инициализировать хотя бы один из источников света. Для включения и отключения источников света также используются команды Enable и Disable, в качестве параметра указывается имя константы, определяющей номер источника света:
C#: EnableCap.Light0.. EnableCap.Light7 Object Pascal: GL_LIGHT0…GL_LIGHT7
Константы имеют однотипное название: последовательность символов "LIGHT" и номер источника света. Источники света нумеруются начиная с нуля.
Количество источников света определяется реализацией библиотеки. Библиотека OpenGL поддерживает не менее 8 источников света.
Свойства "нулевого" источника света (EnableCap.Light0 в библиотеке OpenTK (C#) и GL_LIGHT0 в Object Pascal) отличаются от других источников света. Он расположен в бесконечности и освещает сцену в отрицательном направлении оси OZ. Другие источники света после инициализации OpenGL имеют нулевую интенсивность всех составляющих освещения, поэтому для их использования необходимо кроме инициализации источника света, выполнить настройку их свойств. Так как "нулевой" источник света не требует дополнительной настройки, то часто используется для освещения, если нужен всего один источник света.
Если все объекты на сцене будут всегда освещены, то включить режим освещения и источник света можно сразу после инициализации библиотеки в обработчике события формы OnCreate в программе на Object Pascal (Delphi) или события Load в программе на C# с помощью команд:
C#: GL.Enable(EnableCap.Lighting); GL.Enable(EnableCap.Light0); Object Pascal: glEnable(GL_LIGHTING); glEnable(GL_LIGHT0);
После включения режима освещения для отображения граней примитивов используются свойства материала. Команда Color, определяющая цвет
OpenGL использует модель освещения, в которой моделируются несколько составляющих освещения: рассеянная, диффузная, отраженная и эмиссионная составляющие.
Это свет, попадающий на освещаемый объект после отражения от других объектов.
Его еще также называют рассеянным светом в окружающей среде. Направление его нельзя определить. Это, например, свет, отраженный от стен в комнате. В модели освещения OpenGL интенсивность рассеянного света не зависит от положения источника света и от точки наблюдения. При выключении источника света эта составляющая света также исчезает, т. к. обусловлена она источником света.
Это направленный свет от источника света, который равномерно рассеивается поверхностью. Он характерен для матовых поверхностей. Интенсивность освещения объектов рассеянным светом не зависит от точки наблюдения, пропорциональна косинусу угла между направлением нормали к поверхности и направлением на источник света, а также пропорциональна размеру вектора нормали.
Это направленный свет от источника света, который отражается в определенном направлении. Он характерен для зеркальных поверхностей. Интенсивность зависит от трех факторов: положения источника света, нормали к поверхности и точки наблюдения. Для этой составляющей виден только тот свет, у которого угол падения равен углу отражения и положение наблюдателя совпадает с направлением отраженного света.
Не добавляет освещение в общую сцену, делает объекты более яркими. Например, такая составляющая может использоваться для моделирования фар автомобиля, лампы накаливания.
Для каждой грани примитива параметры освещения задаются индивидуально. Набор параметров освещения для каждой грани в библиотеке OpenGL называется свойствами материала. Поэтому можно сказать, что каждая грань примитива имеет свой материал. Свойства материала определяют рассеянную, диффузную, отражённую и эмиссионную составляющую освещения материала.
Для задания свойств материала используется команда библиотеки OpenGL:
Material[i f][v](face, pname: GLenum; param: GLType)
Параметр .
| Назначение параметра | Значение параметра | |
|---|---|---|
| Библиотека OpenTK, C# | Object Pascal | |
| Лицевые грани многоугольников | MaterialFace.Front | GL_FRONT |
| Обратные грани многоугольников | MaterialFace.Back | GL_BACK |
| Лицевые и обратные грани многоугольников | MaterialFace.FrontAndBack | GL_FRONT_AND_BACK |
Параметр .
| Назначение параметра, значение по умолчанию | Значение параметра | |
|---|---|---|
| Object Pascal | OpenTK (C#) | |
Цвет и интенсивность рассеянной составляющей освещения материала, (0.2, 0.2, 0.2, 1) | GL_AMBIENT | MaterialParameter.Ambient |
Цвет и интенсивность диффузной составляющей освещения материала, (0.8, 0.8, 0.8, 1) | GL_DIFFUSE | MaterialParameter.Diffuse |
Цвет и интенсивность зеркальной составляющей освещения материала, (0, 0, 0, 1) | GL_SPECULAR | MaterialParameter. |
Зеркальная экспонента, (0.0) | GL_SHININESS | MaterialParameter.Shininess |
Цвет и интенсивность излучаемого света материала, (0, 0, 0, 1.0) | GL_EMISSION | MaterialParameter.Emission |
| Цвет и интенсивность рассеянной и диффузной составляющих освещения материала | GL_AMBIENT_AND_DIFFUSE | MaterialParameter.AmbientAndDiffuse |
Пример определения диффузной составляющей для лицевой грани материала приведен в листинге 6.1 на C# и в листинге 6.2 на Object Pascal:
GL.Material(MaterialFace.Front, MaterialParameter.Diffuse,
new float[] { 1f, 0.2f, 0.2f, 1.0f });
var params: TGLArrayf4; begin ... params[0] := 1; params[1] := 0.2; params[2] := 0.2; params[3] := 1; glMaterialfv(GL_FRONT, GL_DIFFUSE, @params); ... end;
Тип TGLArrayf4 объявлен в файле OpenGL.pas и определяет массив вещественных значений типа GLfloat.
Направление нормалей имеет значение для двух составляющих освещения: диффузной и отраженной. Направление нормали может быть определено индивидуально для каждой вершины. Для определения нормали используется команда:
Normal [3] [b s I f d][v] (coords)
И в Object Pascal и в C# для реализации команды используется набор процедур (Object Pascal) и статических методов класса GL (C#), которые различаются параметрами. Ниже приведен один из вариантов реализации команды:
C#: void Normal3(float nx, float ny, float nz); Object Pascal: procedure glNormal3f (nx, ny, nz: GLFloat);
По умолчанию направление нормалей [0,0,1], т.е. они направлены вдоль оси OZ и имеют единичный размер.
В качестве примера построим три квадрата, составляющих грани куба, с использованием библиотеки OpenTK на языке C# () и на языке программирования Object Pascal ().
private void glControl1_Paint(object sender, PaintEventArgs e)
{
// очистка буферов цвета и глубины
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// поворот изображения
GL.LoadIdentity();
GL.Rotate(AngleX, 1.0, 0.0, 0.0);
GL.Rotate(AngleY, 0.0, 1.0, 0.0);
GL.Rotate(AngleZ, 0.0, 0.0, 1.0);
// формирование осей координат
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.Light0);
float n = 0.5f; // половина длины ребра куба
GL.Color3(1f, 0f, 0f);
GL.Begin(BeginMode.Quads);
GL.Normal3(0f, 0f, 1f);
GL.Vertex3(0.5f, 0.5f, 0.5f);
GL.Vertex3(-0.5f, 0.5f, 0.5f);
GL.Vertex3(-0.5f, -0.5f, 0.5f);
GL.Vertex3(0.5f, -0.5f, 0.5f);
GL.End();
GL.Color3(0f, 1f, 0f);
GL.Begin(BeginMode.Quads);
GL.Normal3(0f, 0f, -1f);
GL.Vertex3(0.5f, 0.5f, -0.5f);
GL.Vertex3(0.5f, -0.5f, -0.5f);
GL.Vertex3(-0.5f, -0.5f, -0.5f);
GL.Vertex3(-0.5f, 0.5f, -0.5f);
GL.End();
GL.Color3(0f, 0f, 1f);
GL.Begin(BeginMode.Quads);
GL.Normal3(-1f, 0f, 0f);
GL.Vertex3(-0.5f, 0.5f, 0.5f);
GL.Vertex3(-0.5f, 0.5f, -0.5f);
GL.Vertex3(-0.5f, -0.5f, -0.5f);
GL.Vertex3(-0.5f, -0.5f, 0.5f);
GL.End();
GL.Disable(EnableCap.Lighting);
// завершение формирования изображения
GL.Flush();
GL.Finish();
glControl1.SwapBuffers();
}
procedure TForm1.FormPaint(Sender: TObject);
var
n: Double;
begin
glClearColor (1, 1, 1, 1); // цвет фона
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
// установка видовой матрицы в качестве текущей
glMatrixMode(GL_MODELVIEW);
// поворот изображения
glLoadIdentity;
glRotatef(AngleX, 1.0, 0.0, 0.0);
glRotatef(AngleY, 0.0, 1.0, 0.0);
glRotatef(AngleZ, 0.0, 0.0, 1.0);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
n := 0.5; // половина длины ребра куба
glColor3f(1, 0, 0);
glBegin (GL_QUADS);
//glNormal3f(0, 0, -1);
glVertex3f (0.5, 0.5, 0.5);
glVertex3f (-0.5, 0.5, 0.5);
glVertex3f (-0.5, -0.5, 0.5);
glVertex3f (0.5, -0.5, 0.5);
glEnd;
glColor3f(0, 1, 0);
glBegin (GL_QUADS);
//glNormal3f(0, 0, 1);
glVertex3f (0.5, 0.5, -0.5);
glVertex3f (0.5, -0.5, -0.5);
glVertex3f (-0.5, -0.5, -0.5);
glVertex3f (-0.5, 0.5, -0.5);
glEnd;
glColor3f(0, 0, 1);
glBegin (GL_QUADS);
//glNormal3f(1, 0, 0);
glVertex3f (-0.5, 0.5, 0.5);
glVertex3f (-0.5, 0.5, -0.5);
glVertex3f (-0.5, -0.5, -0.5);
glVertex3f (-0.5, -0.5, 0.5);
glEnd;
glDisable(GL_LIGHTING);
// завершение формирования изображения
glFlush;
glFinish;
SwapBuffers(DC);
end;
(рис 6.1) Вид освещённого фрагмента куба без указания направления нормалей для примитивов |
(рис 6.2) Вид освещённого фрагмента куба с указанием направления нормалей для примитивов |
|---|
На рис 6.1 видно, что прямоугольники освещаются неестественно, так как все грани имеют одинаковую освещенность. Объясняется это направлением нормалей. По умолчанию (после инициализации библиотеки) нормали направлены вдоль оси OZ, поэтому для всех граней интенсивность освещенности оказывается одинаковой.
Для реальных объектов направление нормали перпендикулярно касательной к их поверхности. В библиотеке OpenGL направление нормалей может быть задано для каждой вершины произвольным.
Чтобы получить более реалистичное освещение необходимо определить направление нормалей для каждой грани. Для этого в и достаточно убрать комментарии со строчек кода с командой ).
Как можно наблюдать на рис 6.2, после указания направления нормалей перпендикулярно граням, освещённость стала для граней различной и зависит от их ориентации в пространстве. Освещение прямоугольников стало более естественным.
Направление нормали указывается для каждой вершины. Если нормаль не указана перед вызовом команды Vertex, то используется текущее значение нормали, которое было последний раз задано с помощью команды Normal или значение нормали по умолчанию. Возможность индивидуального определения нормалей для вершин позволяет реализовать довольно сложные визуальные эффекты.
На рис 6.1 и рис 6.2 освещены только лицевые грани примитивов. Это связано с направлением нормалей к граням примитивов. Нормали направлены изнутри наружу, поэтому освещаются внешние грани. Если изменить направление нормалей на противоположное, то будут освещаться обратные грани примитивов.
Цвет примитивов на рисунках имеет различные оттенки серого цвета. Это обусловлено свойствами "нулевого" источника света и свойствами материала по умолчанию.
В и направление нормалей было довольно просто определить, так как расположение примитивов было перпендикулярно осям координат. В некоторых других случаях определение направления нормалей также не является сложной задачей. Например, для вершин сферы направление нормалей совпадает с радиус-вектором. Для боковой грани цилиндра – с радиус вектором окружности.
Выполнить определение направления нормалей для примитивов, которые могут иметь произвольное положение в пространстве, можно вычислив векторное произведение векторов их ребер. В этом случае вычисленная нормаль будет направлена перпендикулярно ребрам примитива, которые использовались для вычисления нормали.
Для вычисления нормали необходимо выбрать 3 вершины многоугольника, которые не лежат на одной прямой. Если $$V1, V2, V3$$ – координаты выбранных вершин, то вектора $$\vec{V} $$ и $$\vec{W} $$, построенные на основе этих вершин:
$$\vec{V}=V1-V2\\\vec{W}=V3-V3$$Векторное произведение $$\vec{V} $$ и $$\vec{W} $$ можно определить по формуле:
$$\vec{N}=(v_x,V_y,V_z)\times(W_x,W_y,W_z)=[(V_y\timesW_z-W_y\timesV_z), (V_x\timesW_z-W_x\timesV_z), (V_x\timesW_y-W_x\timesV_y)] $$При вычисленении нормалей они могут получить различный размер. Так как на освещенность примитивов влияет не только направление нормалей, но и их размер, то это также необходимо учитывать.
Если не предполагается специально для задания интенсивности освещения использовать размер нормалей, то необходимо чтобы размер всех нормалей был единичным.
Операцию приведения размера нормали к единичному при сохранении её направления называют нормализацией нормали.
Длина исходного вектора:$$N=\sqrt{x^2+y^2+z^2}$$.
Нормализованный вектор: $$\vec{N_n}=(x/N,y/N,z/N)$$.
OpenGL может выполнить автоматически нормализацию нормалей. По умолчанию этот режим отключен. Для включения и отключения используются соответственно команды Enable и Disable со значением параметра:
C#: EnableCap.Normalize Object Pascal: GL_NORMALIZE
В лекции рассмотрена инициализация режима освещения, измененение свойств материала, формирование нормалей.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.