Opengl освещение и все что с ним связано


Содержание

Почему мой цвет исчезает, когда я включаю освещение в OpenGL?

Я разрабатываю графическое приложение на С++ с OpenGL API и GLUT.

Чтобы добавить освещение, я внес следующие изменения в мою модельную модель:

Освещение в основном работает, я верю, но цвета моих объектов все уходят. Все, что я вижу, это черный/белый силуэт моей общей фигуры.

Мне было интересно, почему это?

Когда освещение включено, цвет вершины не определяется цветом, установленным glColor или glColorPointer , а текущими установленными цветами материала в сочетании с цветами огней с использованием вычислений освещения.

Итак, чтобы изменить цвет объекта, перед рендерингом вам нужно изменить настройку материала (который по умолчанию является диффузным серым материалом), используя glMaterial . По существу, имеется соответствующий цвет материала для каждого из разных светлых цветов ( GL_DIFFUSE . ) наряду с некоторыми дополнительными свойствами для приближения светоизлучающих материалов ( GL_EMISSION ) и контроля шероховатости материала ( GL_SHININESS ). Прочтите некоторые вводные материалы по функциям освещения OpenGL, чтобы понять их работу.

Что вы можете сделать, чтобы быстро адаптировать свой код от простой раскраски к освещению (или для включения свойств материала на вершине), использовать цветной материал. Вызывая glEnable(GL_COLOR_MATERIAL) и устанавливая соответствующее сопоставление с glColorMaterial , вы можете настроить OpenGL для изменения определенного цвета материала, всякий раз, когда вы меняете текущую вершину цвет (используя либо glColor , либо glColorPointer ).

Функция материала цвета OpenGL обеспечивает менее дорогостоящий способ изменить параметры материала. При включенном цветовом материале материал цвета отслеживают текущий цвет. Это означает, что вместо использования относительно дорогостоящая процедура glMaterialfv , вы можете использовать glColor3f .

Вот пример использования функции цветного материала для изменения диффузный цвет для каждой вершины треугольника:

Рассмотрим более дорогую кодовую последовательность, если glMaterialfv явно используется:

Если вы рендерите объекты, требующие частого простого материала изменения, попробуйте использовать режим цветных материалов. Однако существует общая ошибка, возникающая при включении режима цветного материала. когда цветной материал включен, OpenGL немедленно изменяет материал цвета, контролируемые состоянием цветного материала. Рассмотрим следующее фрагмент кода для инициализации нового контекста рендеринга OpenGL:

В каком состоянии будут отображаться цвета передних окружающих и диффузных материалов выполнение вышеуказанного фрагмента кода? Хотя программист может иметь Предполагалось, что состояние окружающего материала должно быть (0.1, 0.1, 0.1, 1.0) и состояние диффузного материала (0.3, 0.5, 0.6, 1.0) , то есть что происходит.

Результирующее состояние диффузного материала — это то, что планировал программист, но полученное состояние окружающего материала довольно неожиданно (1.0, 1.0, 1.0, 1.0) . Как это произошло? Ну, помните, что режим цветного материала сразу начинает отслеживать текущий цвет, когда включен. Начальное значение для параметров цветового материала GL_FRONT_AND_BACK и GL_AMBIENT_AND_DIFFUSE (вероятно, не то, что вы ожидали!).

Так как включение режима цветного материала сразу начинает отслеживать текущий цвет, как состояния окружающего, так и диффузного материала обновлено до (1.0, 1.0, 1.0, 1.0) . Обратите внимание, что эффект начальный glMaterialfv теряется. Далее, состояние цветного материала чтобы просто изменить передний диффузный материал. Наконец, Вызов glColor3f изменяет диффузный материал на (0.3, 0.5, 0.6, 1.0) . Состояние окружающего материала заканчивается (1.0, 1.0, 1.0, 1.0) .

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

OpenGL: освещение

Могу сказать как создать spot-источник:

// Во время инициализации GL

float pos[4], diff[4], cutff;

glEnable (GL_LIGHTING); пlLightfv (GL_LIGHT0, GL_POSITION, pos); glLightfv (GL_LIGHT0, GL_DIFFUSE, diff); glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 4); glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, cutoff); glEnable (GL_LIGHT0);

Первые три элемента pos-координаты, четвертый-1.0 (Не помню точно что это значит). Первые три элемента diff-диффузные r,g,b, четвертый-1.0 (тоже не помню что это). cutoff-дальность.

Re: OpenGL: освещение

Сорри за формат. Не так давно на этом форуме. Не привык еще.

Блог Андрея Монахова

Разработка приложений Android OpenGL ES


Ссылки

Поиск

8 октября 2012 г.

OpenGL ES 2.0. Урок второй-Освещение в шейдере

Вычислим скалярное произведение вектора нормали n_normal и вектора lightvector :
dot(n_normal, lightvector)
В общем случае скалярное произведение может быть отрицательным, если угол между векторами больше 90 градусов. Отрицательные значения нам нужно отсечь. Поэтому выберем максимальное значение между скалярным произведением и нулем:
max(dot(n_normal, lightvector), 0.0)
Умножим полученное значение на некоторый коэффициент диффузного освещения k_diffuse и получим яркость диффузного освещения пикселя:
float diffuse = k_diffuse * max(dot(n_normal, lightvector), 0.0);
Кстати, число с плавающей точкой в шейдерах нужно указывать как 0.0 . Если указать просто 0 , то будет ошибка и шейдер не скомпилируется.

Теперь вычислим вектор, указывающий из точки освещения на камеру и нормализуем его:
vec3 lookvector = normalize(u_camera — v_vertex);
Далее нам нужно вычислить косинус угла между отраженным вектором и направлением на камеру. Это скалярное произведение двух единичных векторов:
dot(lookvector,reflectvector)
Отсекаем отрицательные значения скалярного произведения при помощи функции max :
max(dot(lookvector,reflectvector),0.0)
При отражении света на поверхности появляются блики. Размер блика можно регулировать при помощи параметра блеска. Вычисленное значение скалярного произведения нужно возвести в степень блеска. Для возведения в степень в GLSL предусмотрена функция pow Обычно значение блеска выбирают в размере несколько десятков. При увеличении блеска размер блика уменьшается, но яркость его увеличивается. И наоборот, чем меньше блеск, тем больше размер блика, но яркость его становится меньше. Пусть, для примера, блеск будет равен 40. Возведем полученное скалярное произведение в степень 40:
pow( max(dot(lookvector,reflectvector),0.0), 40.0 )
Умножим полученное значение на коэффициент зеркального освещения k_specular и получим яркость зеркального освещения для данного пикселя:
float specular = k_specular * pow( max(dot(lookvector,reflectvector),0.0), 40.0 );

Для того, чтобы получить цвет пикселя с учетом освещения нужно сложить фоновую диффузную и зеркальную части освещения ambient + diffuse + specular и умножить на вектор цвета пикселя, полученного при интерполяции цветов вершин v_color .
gl_FragColor = (ambient+diffuse+specular)* v_color ;
Если мы не хотим разукрашивать пиксели интерполированными цветами вершин достаточно определить вектор белого цвета:
vec4 one=vec4(1.0,1.0,1.0,1.0);
и умножить на него яркость освещения:
gl_FragColor = (ambient+diffuse+specular)*one ;
Для начала рассмотрим этот черно-белый вариант освещения.

Напишем рабочий код для рисования квадрата с освещением. Напомню, что класс Shader был описан в первом уроке. Отмечу, что при создании экрана шейдерные объекты разрушаются. Поэтому объект класса Shader должен создаваться в методе onSurfaceCreated.

Opengl освещение и все что с ним связано

Фиксированный конвейер OpenGL содержит механизмы расчёта освещения и наложения тумана. В примере показано и объяснено, как их использовать.

Содержание

Модель освещения в фиксированном конвейере OpenGL

Фиксированный конвейер OpenGL позволяет использовать определённую математическую модель симуляции освещения — модель Фонга, а также определённую модель интерполяции освещения по всему полигону — модель Гуро (хотя для интерполяции тоже есть своя модель Фонга). Существуют другие модели освещения и интерполяции, но в рамках фиксированного конвейера реализовать их не получится.

Одно из центральных звеньев модели освещения Фонга — это закон расчёта рассеянного освещения (англ. diffuse), также известный как закон Ламберта:

Закон Ламберта проявляет себя в простом наблюдении: чем меньше угол падения солнечных лучей, тем меньше освещена поверхность. Ночью угол падения отрицательный, т.е. путь солнечных лучей перекрывает поверхность где-то на другой стороне Земли. В результате рассеянный (диффузный) свет отсутствует вовсе.

Илон Маск рекомендует:  Что такое код enumfonts

Компоненты освещения в модели Фонга

Расчёт рассеянного освещения по закону Ламберта даёт неприятный эффект: обратная по отношению к источнику света сторона объекта не освещена. В реальном мире рассеяный свет отражается от стен комнаты и освещает даже те поверхности, на которые не попадают прямые лучи от источника света. В фиксированном конвейере OpenGL этот эффект грубо эмулируется путём умножения “фонового” цвета материала на “фоновую” интенсивность источника света. Этот компонент цвета освещённой поверхности обозначается константой GL_AMBIENT .

Рассеянное освещение, рассчитаное по закону Ламберта, обозначается константой GL_DIFFUSE .

Также модель Фонга вносит третью компоненту — световые блики, которые проявляются, когда угол падения лучей на тело практически равен углу отражения луча, попадающего в камеру. Эта компонента освещения обозначается константой GL_SPECULAR :

Вот так выглядят три компонента и результат их сложения:

RGBA-цвета всех трёх компонент попросту складываются покомпонетно, и полученные в результате Red, Green, Blue компоненты обрезаются в границах [0, 1] . В результате очень ярко освещённый белым источником светло-жёлтый объект может стать просто белым — цвет <5.3, 3.2, 1.1, 1>будет обрезан до белого цвета <1, 1, 1, 1>.

Между прочим, в OpenGL есть ещё одна компонента освещения: GL_EMISSION. Она задаёт собственную светимость материала, не зависящую от освещения, и позволяет грубо симулировать светящиеся объекты. Компонента крайне редко используется, и мы не станем её рассматривать.

8 источников света

Фиксированный конвейер OpenGL позволяет симулировать не более 8 источников света, поскольку каждый активный источник даёт одинаковый и вполне заметный прирост трудозатрат на растеризацию трёхмерной сцены. Источники света обозначаются константами от GL_LIGHT0 до GL_LIGHT7 . В некоторых реализациях OpenGL доступны дополнительные источники с индексами от GL_LIGHT8 , но написанный с их использованием код не будет работать на большинстве видеокарт.

Включить систему освещения или активировать отдельный источник можно функцией-командой glEnable .


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

Разрабатываем класс “Направленный источник света”

В OpenGL можно симулировать три разных типа источников света:

  • бесконечно удалённый направленный (такой, как Солнце или Луна)
  • точечный источник на фиксированной позиции (такой, как светлячок)
  • прожекторный источник (*англ. spotlight), то есть точечный источник с ограничением распространения света некоторым конусом

Поэтому для начала введём интерфейс ILightSource и абстрактный класс CAbstractLightSource:

Релизация getter/setter методов тривиальна и не заслуживает отдельного рассмотрения. Зато мы рассмотрим определение метода SetupImpl:

Для установки параметров источника света используется семейство функций glLight, выбранная функция glLightfv , как понятно из суффикса fv (float variadic), принимает начало массива float неопределённой длины. Длину массива видеодрайвер выбирает в зависимости от параметра источника света, указанного во втором параметре функции.

Как направленный источник света, так и точечный имеют единый параметр — четырёхкомпонентный вектор GL_POSITION. Здесь опять используется трюк с однородным представлением координат: точка делает источник света точечным, а вектор — направленным. Заложим эту разницу в исходном коде:

Разрабатываем класс “Точечный источник света”

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

В примере к этой статье нет класса CSpotlightSource. Вы можете реализовать его самостоятельно путём наследования CPositionLightSource и расширения его установкой и применением параметров GL_SPOT_DIRECTION, GL_SPOT_EXPONENT, GL_SPOT_CUTOFF. Больше информации можно найти в статье на glprogramming.com в разделе “Spotlights”.

Добавляем источник света к окну

Добавим новое поле m_sunlight класса CWindow :

Теперь можно настроить источник в конструкторе, и вывести его в OnDrawWindow. Заметим, что мы не будем устанавливать источнику света компоненту GL_SPECULAR, потому что она по своей природе предназначена для создания светового блика, но в фиксированном конвеере OpenGL для освещения используется интерполяция Гуро, из-за которой вся грань куба будет иметь одинаковый световой блик и окажется окрашенной в один цвет. Так будет выглядеть реализация конструктора и OnDrawWindow:

Цветовые компоненты материала.

Для задания цветовых компонент материала в OpenGL существует семейство функция glMaterial*. В случае, если вы используете такой метод задания материала, вы должны задать его вне блока glBegin/glEnd, и материал будет действовать на группы выводимых примитивов, пока его не изменят.

Но в OpenGL есть и другой способ задания материала, потенциально более гибкий и производительный: определение цвета материала по цветам вершин (не стоит забывать, что цвет вершины интерполируется по всей примитивной грани). Для включения режима “цвет как материал” следует включить флаг состояния драйвера GL_COLOR_MATERIAL и с помощью функции glColorMaterial выбрать, как отображать цвет фрагмента грани на компоненты цвета материала этого фрагмента. Это можно сделать в методе SetupOpenGLState:

Нормали к поверхности

Для корректного расчёта освещения фиксированному конвейеру нужны дополнительные сведения о поверхности — перпендикуляры к точкам поверхности единичной длины. Такие перпендикуляры называются нормалями, а процесс деления вектора на собственную длину ради получения вектора единичной длины называется нормализацией. Процесс нормализации выполняет, например, функция glm::normalize библиотеки GLM, принимающая единственным параметром нормализуемый вектор.

  • нормали используются для расчёта рассеянной компоненты света GL_DIFFUSE по закону Ламберта: зная вектор нормали и вектор направления света, несложно вычислить угол падения лучей на поверхность
  • нормали также используются для расчёта бликовой компоненты света GL_SPECULAR по модели Фонга: угол падения и угол отражения света вычисляются с помощью нормали к поверхности

Нормаль — это атрибут вершины, добавляемой в графический примитив, такой как GL_TRIANGLE, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN. Для её установки в Immediate Mode служит семейство функций glNormal3*.

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

Однако, в OpenGL это правило можно нарушать: программист может задавать разные нормали разным вершинам треугольника, что приведёт к разным цветам на вершинах и интерполяци цвета по всей грани. Это позволяет, например, создать эффект “гладкости” тела, скрыв от наблюдателя тот факт, что тело собрано из треугольников. В данном случае нам не нужен эффект гладкой поверхности, поэтому нормаль к вершине мы будем вычислять с помощью нормализации векторного произведения двух сторон треугольника.


Псевдокод вычисления нормали:

Изменяем класс CIdentityCube

Мы добавим в класс определение и установку нормалей к граням с помощью векторного произведения. Мы также добавим возможность выборочно устанавливать цвета отдельных граней куба. Для выбора грани при установке цвета мы применим перечислимые типы (enum). Об особенностях и применении enum есть отдельная статья. Интерфейс для установки цвета будет выглядеть следующим образом:

Также нам нужно изменить описание граней куба, добавив новую структуру STriangleFace:

Мы изменим конструктор CIdentityCube, чтобы задать белый цвет цветом граней по умолчанию:

И теперь можно реализовать метод Draw, не забыв о необходимости выбора цвета и нормали к грани куба:

Запуск и проверка

После добавления источника света окно запущенной программы должно будет так:

Если же что-то не работает, используйте следующий чеклист:

  • включено ли освещение командой glEnable(GL_LIGHTING) ?
  • включён ли i-й источник света командой glEnable(GL_LIGHTi) ?
  • установлены ли параметры источника света?
  • установлен ли цвет материала с помощью glMaterial или glColorMaterial?
  • правильно ли выбраны нормали граней объектов?
  • установлена ли матрица GL_MODELVIEW камеры прежде, чем установлен источник света?

Наложение тумана

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

Для того, чтобы включить наложение тумана, необходимо вызвать функцию glEnable с параметром GL_FOG. Для управления параметрами тумана служит семейство функций glFog*, позволяющих задать цвет тумана (fog color), плотность (density), начальную и конечную дистанцию для линейного тумана (start depth и end depth).

В OpenGL коэффициент смешивания для тумана может быть рассчитан по одной из следующих формул:

Полученный коэффициент f приводится к диапазону от 0 до 1. На его основе результирующий цвет фрагмента вычисляется по следующей формуле:

Настройку окна выделим в отдельный метод “SetupFog”, который будем вызывать в “OnDrawWindow”. Также мы добавим обработку клавиши “F”, которая должна включать и выключать отображение тумана, и изменим цвет фона с чёрного на цвет тумана (инача на чёрный фон туман накладываться не будет).

Илон Маск рекомендует:  Assembler & win32 курс молодого бойца

Боремся с алиасингом

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

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

В трёхмерной графике такой подход затруднителен — примитивов и операций достаточно много, реализовать универсальный метод рисования со сглаживанием для каждого фрагмента практически невозможно. Однако, есть универсальное решение, работающее на уровне постобработки кадра: достаточно делить примитивы на фрагменты не на уровне пикселей, а на уровне подпикселей (subpixels), и затем выводить конечный цвет пикселя путём интерполяции входящих в него подпикселей.

Настраивать такой режим сглаживания следует ещё при создании окна. В библиотеке SDL2 за это отвечают два атрибута SDL_GL: “SDL_GL_MULTISAMPLEBUFFERS” и “SDL_GL_MULTISAMPLESAMPLES”. Мы установим эти атрибуты в методе Show класса окна:

После таких изменений края становятся сглаженными, что можно заметить при увеличении фрагмента скриншота в 6 раз:

Результат

Вы можете взять полный пример к уроку на github. А вот так выглядит окно после запуска:

Освещение в OpenGL


December 2020

353 раз

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

1 ответы

1st: You must supply normals.

2nd: The OpenGL fixed function pipeline evaluated illumination only at the vertices and then does barycentric color interpolation. Corners of a box with a light source somewhere inside receive the least light. With a box consisting of only 6 quads you will not get a nice falloff, but only dimly lit walls. You either have to use a fragment shader to implement per fragment lighting (recommended) or tesselate your quads down into a reasonable number of smaller quads forming the wall, so that there are enough interpolation sampling points, where illumination is evaluated.

Opengl освещение и все что с ним связано

Без источника света изображения не видно. Что бы инициализировать источник, и включить обработчик расчёта воздействия источника на объекты достаточно выполнить команды: glEnable(gl_lighting);// включить режима анализа освещения

glEnable(gl_light0); // включить в сцену конкретный (нулевой) источник, с его характеристиками

Для отключения источника используется функция Disable(). Источник света по умолчанию располагается в пространстве с координатами (0,0,∞). Можно создавать источник света в любой точке пространства изображений.

В библиотеке OpenGl поддерживаются источники света четырех типов:

  • фонового освещения (ambient lighting),
  • точечные источники (point sources),
  • прожекторы (spotlights),
  • удаленные источники света (distant light).

Каждый источник света имеет свой набор характеристик.
Характеристики источника света, соответствуют параметрам модели Фонга.
Для установки векторных параметров используется функция glLightfv(), которая имеет следующий формат :

glLightfv(source, parameter, pointer_to_array);

Существует четыре векторных параметра, которые определяют положение и направление лучей источника и цветовой состав его составляющих – фоновой, диффузионной и зеркальной.
Для установки скалярных параметров в OpenGL служит функция glLightf():

glLightf(source, parameter, value);

Пусть, например, требуется включить в сцену источник GL_LIGHT0, который должен находиться в точке (1.0, 2.0, 3.0). Положение источника сохраняется в программе в виде точки в однородных координатах:

Если четвертый компонент этой точки равен нулю, то точечный источник превращается в удаленный, для которого существенно только направление лучей:

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

glLightfv(GL_LIGHT0, GL_POSITION, light0_pos);

glLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);

glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);

glLightfv(GL_LIGHT0, GL_SPECULAR, specular0);

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

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

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


glLightf(GL_LIGHT0, GL_CONSTANT_ATTENATION, a);

Для преобразование точечного источника в прожектор нужно задать направление луча прожектора (GL_SPOT_DIRECTION), показатель функции распределения интенсивности (GL_SPOT_EXPONENT) и угол рассеяния луча (GL_SPOT_CUTTOF). Эти параметры устанавливаются с помощью функций glLightf() и glLightfv().

Параметры, устанавливаемые для источников света по умолчанию приведены в таблице 3.

Параметры, устанавливаемые для источников света по умолчанию

Имя параметра
GL_AMBIENT

ambient RGBA intensity of light

GL_DIFFUSE

diffuse RGBA intensity of light

GL_SPECULAR

specular RGBA intensity of light

GL_POSITION

(0.0, 0.0, 1.0, 0.0) ( x, y, z, w ) position of light GL_SPOT_DIRECTION

( x, y, z ) direction of spotlight

GL_SPOT_EXPONENT GL_SPOT_CUTOFF

spotlight cutoff angle

GL_CONSTANT_ATTENUATION

constant attenuation factor

GL_LINEAR_ATTENUATION

linear attenuation factor

GL_QUADRATIC_ATTENUATION

quadratic attenuation factor

Почему мой цвет исчезает, когда я включаю освещение в OpenGL?

Я разрабатываю графическое приложение на С++ с OpenGL API и GLUT.


Чтобы добавить освещение, я внес следующие изменения в мою модельную модель:

Освещение в основном работает, я верю, но цвета моих объектов все уходят. Все, что я вижу, это черный/белый силуэт моей общей фигуры.

Мне было интересно, почему это?

Когда освещение включено, цвет вершины не определяется цветом, установленным glColor или glColorPointer , а текущими установленными цветами материала в сочетании с цветами огней с использованием вычислений освещения.

Итак, чтобы изменить цвет объекта, перед рендерингом вам нужно изменить настройку материала (который по умолчанию является диффузным серым материалом), используя glMaterial . По существу, имеется соответствующий цвет материала для каждого из разных светлых цветов ( GL_DIFFUSE . ) наряду с некоторыми дополнительными свойствами для приближения светоизлучающих материалов ( GL_EMISSION ) и контроля шероховатости материала ( GL_SHININESS ). Прочтите некоторые вводные материалы по функциям освещения OpenGL, чтобы понять их работу.

Что вы можете сделать, чтобы быстро адаптировать свой код от простой раскраски к освещению (или для включения свойств материала на вершине), использовать цветной материал. Вызывая glEnable(GL_COLOR_MATERIAL) и устанавливая соответствующее сопоставление с glColorMaterial , вы можете настроить OpenGL для изменения определенного цвета материала, всякий раз, когда вы меняете текущую вершину цвет (используя либо glColor , либо glColorPointer ).

Функция материала цвета OpenGL обеспечивает менее дорогостоящий способ изменить параметры материала. При включенном цветовом материале материал цвета отслеживают текущий цвет. Это означает, что вместо использования относительно дорогостоящая процедура glMaterialfv , вы можете использовать glColor3f .

Вот пример использования функции цветного материала для изменения диффузный цвет для каждой вершины треугольника:

Рассмотрим более дорогую кодовую последовательность, если glMaterialfv явно используется:

Если вы рендерите объекты, требующие частого простого материала изменения, попробуйте использовать режим цветных материалов. Однако существует общая ошибка, возникающая при включении режима цветного материала. когда цветной материал включен, OpenGL немедленно изменяет материал цвета, контролируемые состоянием цветного материала. Рассмотрим следующее фрагмент кода для инициализации нового контекста рендеринга OpenGL:

В каком состоянии будут отображаться цвета передних окружающих и диффузных материалов выполнение вышеуказанного фрагмента кода? Хотя программист может иметь Предполагалось, что состояние окружающего материала должно быть (0.1, 0.1, 0.1, 1.0) и состояние диффузного материала (0.3, 0.5, 0.6, 1.0) , то есть что происходит.

Результирующее состояние диффузного материала — это то, что планировал программист, но полученное состояние окружающего материала довольно неожиданно (1.0, 1.0, 1.0, 1.0) . Как это произошло? Ну, помните, что режим цветного материала сразу начинает отслеживать текущий цвет, когда включен. Начальное значение для параметров цветового материала GL_FRONT_AND_BACK и GL_AMBIENT_AND_DIFFUSE (вероятно, не то, что вы ожидали!).

Так как включение режима цветного материала сразу начинает отслеживать текущий цвет, как состояния окружающего, так и диффузного материала обновлено до (1.0, 1.0, 1.0, 1.0) . Обратите внимание, что эффект начальный glMaterialfv теряется. Далее, состояние цветного материала чтобы просто изменить передний диффузный материал. Наконец, Вызов glColor3f изменяет диффузный материал на (0.3, 0.5, 0.6, 1.0) . Состояние окружающего материала заканчивается (1.0, 1.0, 1.0, 1.0) .

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

Opengl освещение и все что с ним связано

OpenGL использует модель освещённости, в которой свет приходит из нескольких источников, каждый из которых может быть включён или выключен. Кроме того, существует еще общее фоновое (ambient) освещение.

Для правильного освещения объектов необходимо для каждой грани задать материал, обладающий определенными свойствами. Материал может испускать свой собственный свет, рассеивать падающий свет во всех направлениях (диффузное отражение) или, подобно зеркалу, отражать свет в определенных направлениях.

Пользователь может определить до восьми источников света и их свойства, такие, как цвет, положение и направление. Для задания этих свойств служит процедура gllight < i f >[ v ]( GLenum light , GLenum pname , TYPE param ) , которая задаёт параметры для источника света light , принимающего значения GL _ LIGHT 0 , GL _ LIGHT 1 , . GL _ LIGHT 7 . Параметр pname определяет характеристику источника света, которая задается последним параметром.

Для использования источников света расчёт освещенности следует разрешить командой glEnable(GL_LGHTING) , а применение соответствующего источника света разрешить (включить) командой glEnable , например: glEnable(GL_LIGHT0) .

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

Если параметр w в команде GL_POSITION равен нулю, то соответствующий источник света – направленный и светит в направлении (х, у, z). Если же w отлично от нуля, то это позиционный источник света, находящийся в точке с координатами (x/w, y/w, z/w).

Заданием параметров GL_SPOT_CUTOFF и GL_SPOT_DIRECTION можно создавать источники света, которые будут иметь коническую направленность. По умолчанию значение параметра GL_SPOT_CUTOFF равно 180°, т. е. источник светит во всех направлениях с равной интенсивностью. Параметр GL_SPOT_CUTOFF определяет максимальный угол от направления источника, в котором распространяется свет от него. Он может принимать значение 180° (не конический источник) или от 0 до 90°.

Интенсивность источника с расстоянием, вообще говоря, убывает (параметры этого убывания задаются при помощи параметров GL_CONSTANT_ATTENUATION , GL _ LINEAR _ ATTENUATION и GL _ QUADRATIC _ ATTENUATION ). Только собственное свечение материала и глобальная фоновая освещенность с расстоянием не ослабевают.

Глобальное фоновое освещение можно задать при помощи команды gtLightModel < i f >[ v ] ( GL _ LIGHT _ MODEL _ AMBIENT ambientColor ) .

Местонахождение наблюдателя оказывает влияние на блики на объектах. По умолчанию при расчётах освещённости считается, что наблюдатель находится в бесконечно удалённой точке, т. е. направление на наблюдателя постоянно для любой вершины. Можно включить более реалистическое освещение, когда направление на наблюдателя будет вычисляться для каждой вершины отдельно. Для этого служит команда glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE) .

Для задания освещения как лицевых, так и нелицевых граней (для нелицевых граней вектор нормали переворачивается) служит следующая команда glLightModeli ( GL _ LIGHT _ MODEL _ TWO _ SIDE , GL _ TRUE ) , причём существует возможность отдельного задания свойств материала для каждой из сторон.


Свойства материала, из которого сделан объект, задаются при помощи процедуры glMaterial < i f >[ v ]( GLenum face , GLenum pname , TYPE param ) .

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

Параметр pname указывает, какое именно свойство материала задается.

Расчёт освещённости в OpenGL не учитывает затенения одних объектов другими.

Затенение OpenGL — странное освещение

У меня есть небольшая проблема с моим освещением OpenGL.

Это хорошо отрисовывает модель (чайник из Юты), но у меня есть странные схемы освещения. Модель должна быть плоской, с единственным освещением, освещающим сцену, но я получаю пятнистый свет по всему чайнику:

Это всего лишь простое упражнение для создания загрузчика модели в C ++ с использованием SFML.

Код выглядит следующим образом:

У кого-нибудь есть мысли?

Решение

Источники света OpenGL имеют значения по умолчанию для всех свойств (например, GL_AMBIENT , GL_DIFFUSE , так далее.). В случае GL_LIGHT0 свойство diffuse не установлено в ноль (это то, что вам нужно, чтобы получить только окружающее освещение). Чтобы исправить это, вам нужно сделать

Так как, IIRC, остальные свойства освещения уже равны нулю, что должно дать вам освещение только для окружающей среды, которое удаляет направленную составляющую вашего освещения. Кроме того, режим по умолчанию для glColorMaterial является GL_AMBIENT_AND_DIFFUSE , который устанавливает свойства окружающего и рассеянного материала для цвета входящей вершины. Вы можете подумать о том, чтобы переключить это только на окружающий glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT ); ) также.

Однако коренная причина странности вашего затенения, я думаю, вероятно, связана с ненормативной длиной нормалей. Вы можете попробовать добавить glEnable( GL_NORMALIZE ); перед выполнением световых расчетов.

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

страница 4/5
Дата 05.06.2020
Размер 1.45 Mb.
Тип Книга
    Навигация по данной странице:
  • 6.2 Модель освещения
  • 6.3 Материал
  • 6.4 Лампы и их свойства
Илон Маск рекомендует:  Что такое код domnode &#62;append_sibling
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL

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

6.1 Общие понятия


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

Попробуйте изменить параметры и посмотрите на результат. Нулевую лампу (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)

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);

glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);

gluCylinder(quadObj, 1, 0.5, 2, 10, 10);

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

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

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


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

#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. Я покажу и прокомментирую лишь небольшой пример, использующий три лампы. Для начала, давайте разберем шаблонный пример. С помощью следующих функций разрешаем освещение и включаем нулевую лампу.

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

glLightfv(GL_LIGHT0, GL_POSITION, pos);

glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir);

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

auxInitPosition( 50, 10, 400, 400);

auxInitDisplayMode( AUX_RGB | AUX_DEPTH | AUX_DOUBLE );

auxInitWindow( «Glaux Template» );

glLightfv(GL_LIGHT3, GL_SPECULAR, sp);

glLightfv(GL_LIGHT5, GL_SPECULAR, sp);

glLightfv(GL_LIGHT6, GL_SPECULAR, sp);

glLightfv(GL_LIGHT3, GL_DIFFUSE, color);

glLightfv(GL_LIGHT5, GL_DIFFUSE, color);

glLightfv(GL_LIGHT6, GL_DIFFUSE, color);

glLightfv(GL_LIGHT3, GL_POSITION, pos);

glLightfv(GL_LIGHT5, GL_POSITION, pos);

glLightfv(GL_LIGHT6, GL_POSITION, pos);

glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);

glMaterialf(GL_FRONT, GL_SHININESS, 128.0);

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

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

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