Урок №12. Материалы объектов в OpenGL

  Дмитрий Бушуев  | 

  Обновл. 8 Июн 2020  | 

 408

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

Материалы

В предыдущем уроке мы определили объект и цвет света, чтобы получить визуальное представление данного объекта с учётом фоновой составляющей и интенсивностью зеркального компонента освещения. При описании поверхности объекта мы можем определить цвет материала для каждого из 3-х компонентов освещения: фонового, рассеянного и отраженного/зеркального. Задавая цвет для каждого из компонентов, мы, тем самым, имеем возможность досконально контролировать настройку итогового цвета поверхности. Давайте добавим к этим 3-х компонентам ещё один компонент — блеск. В итоге, мы получим все необходимые свойства для материала:

Во фрагментном шейдере мы создали структуру Material для хранения свойств материала поверхности. Можно также хранить их в виде отдельных uniform-переменных, но способ хранения их в виде структуры делает это более организованным. Сначала мы определяем общую компоновку структуры, а затем просто объявляем uniform-переменную с только что созданной структурой в качестве её типа.

Как вы можете заметить, мы определили вектор цвета для каждого из компонентов освещения модели Фонга:

   вектор ambient определяет, какой цвет отражает поверхность при фоновом освещении (обычно он совпадает с цветом поверхности);

   вектор diffuse определяет цвет поверхности при рассеянном освещении. Рассеянный цвет (так же, как и фоновое освещение) устанавливается на желаемый цвет поверхности;

   вектор specular задает цвет зеркального блика на поверхности (или, возможно, даже отражает специфический для поверхности цвет);

   переменная shininess влияет на рассеивание/радиус зеркального блика.

С помощью данных 4-х компонентов, определяющих материал объекта, мы можем смоделировать различные реальные типы материалов. В данной таблице представлен список свойств объектов, имитирующих реальные материалы. А на следующем рисунке показано влияние некоторых из этих значений на наш куб:

Как вы можете видеть, правильное определение свойств материала поверхности влияет на наше восприятие объекта. Эффекты явно различимы, но для более реалистичных результатов нам нужно будет заменить куб на что-то посерьёзнее. В следующих уроках мы обсудим загрузку моделей объектов более сложных форм.

Определение правильных значений параметров материала объекта — это трудный процесс, в основе которого лежат постоянное экспериментирование с параметрами материалов и наличие большого опыта в данной теме. Очень часто общее визуальное восприятие объекта рушится из-за неправильно подобранного значения материала.

Давайте попробуем с помощью шейдеров реализовать систему материалов объекта.

Настраиваем материалы


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

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

Мы можем задать материал объекта, изменяя в самой программе соответствующую uniform-переменную. Однако, переменная-структура в GLSL по отношению к uniform-переменным не обладает нужными для этого свойствами; она, можно сказать, лишь выполняет для них роль пространства имён. Если мы хотим заполнить структуру, нам придется отдельно устанавливать каждую uniform-переменную, используя в качестве префикса имя структуры:

Далее, мы устанавливаем значения фонового и рассеянного компонентов того цвета, который мы бы хотели видеть у объекта, и задаем значение отраженного/зеркального компонента объекта, соответствующее средне-яркому цвету; мы не хотим, чтобы зеркальный компонент был слишком сильным, поэтому оставляем значение блеска равным 32.

Теперь мы из приложения можем легко влиять на материал объекта. Результат выполнения программы:

Вам случайно не кажется, что сцена выглядит не совсем правильно?

Свойства света

Один из объектов сцены слишком яркий. Причина этого заключается в том, что фоновый, рассеянный и отраженный цвета с полной силой отражаются от любого источника света. Источники света также имеют различные соответствующие значения интенсивности для фонового, рассеянного и отраженного компонентов. В предыдущем уроке мы решили эту проблему, варьируя интенсивность фонового и зеркального светов. Необходимо сделать нечто подобное, но, на этот раз, определив векторы интенсивности для каждого из компонентов освещения. Если бы мы представили переменную lightColor в виде переменной vec3(1.0), то код выглядел бы так:

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

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

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

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

   рассеянная составляющая источника света обычно устанавливается на значение того цвета, который мы хотели бы видеть в нашем свете; часто это ярко-белый цвет;

   отраженная составляющая обычно сохраняется на уровне vec3(1.0), светя при полной интенсивности.

Обратите внимание, что мы также добавили в структуру вектор положения света.

Так же, как и с uniform-переменной материалов, нам нужно обновить фрагментный шейдер:

Затем в самой программе необходимо установить интенсивность света:

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

Сейчас можно относительно легко изменять визуальные аспекты объектов. Поэтому, давайте немного оживим наш кубик!

Различные цвета света


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

Как вы можете видеть, другой цвет света значительно влияет на конечный цвет объекта. Поскольку цвет света непосредственно влияет на то, какие цвета может отражать объект (как мы уже знаем из Урока №10. Цвета в OpenGL), он оказывает значительное влияние на визуальный результат.

Мы можем легко изменить цвета света с течением времени путем изменения фонового и рассеянного цветов света с помощью функций sin() и glfwGetTime():

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

  Google Drive / Исходный код — Урок №12. Материалы и освещение в OpenGL

  GitHub / Исходный код — Урок №12. Материалы и освещение в OpenGL

Упражнения

Задание №1

Можете ли вы сделать так, чтобы изменение цвета света изменило и цвет куба?

Задание №2

Можете ли вы смоделировать некоторые объекты реального мира, определив их соответствующие материалы, как мы это рассматривали в начале данного урока? Обратите внимание, что в таблице значения фонового света и рассеянного света не совпадают; не была учтена интенсивность света. Чтобы правильно установить данные значения, вам нужно будет задать интенсивность всех составляющих компонентов света равными vec3(1.0).

Ответ №2

Решение для сине-зелёного пластикового контейнера (cyan plastic):


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (7 оценок, среднее: 5,00 из 5)
Загрузка...

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

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