Урок №30. Продвинутое освещение в OpenGL

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

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

 1379

В уроках, посвященных освещению, мы кратко обсудили модель освещения Фонга, которая привнесла в наши сцены значительную долю реализма. Данная модель освещения выглядит хорошо, но всё же имеет несколько нюансов, которые мы рассмотрим в этом уроке.

Модель Блинна-Фонга

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

Вы можете видеть, что по краям зеркальная область мгновенно отсекается. Причина, по которой это происходит, заключается в том, что угол между направлением взгляда и вектором отражения не превышает 90 градусов. Если угол больше 90 градусов, то результирующее скалярное произведение становится отрицательным, и это приводит к значению зеркального показателя равного 0.0. Вы, вероятно, думаете, что это не будет проблемой, так как мы всё равно не должны получать свет с углами больше, чем 90 градусов, верно?

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

Здесь проблема должна стать очевидной. Изображение в левой части показывает то отражение в модели Фонга, с которым мы уже знакомы — с углом θ меньше 90 градусов. На правой части изображения мы видим, что угол θ между направлением взгляда и вектором отражения больше 90 градусов, что в результате сводит на нет вклад зеркальной составляющей. Как правило, это не является большой проблемой, так как направление взгляда дальше направления отражения, но если мы используем низкий показатель отражения, то радиус отражения достаточно велик, чтобы вносить свой вклад в подобных ситуациях. Поскольку при углах больше 90 градусов мы обнуляем данную составляющую, то в результате имеем артефакт, представленный на самом первом изображении.

В 1977 году Джеймсом Ф. Блинном была представлена дополненная модель Фонга, названная впоследствии моделью затенения Блинна-Фонга. Модель Блинна-Фонга во многом схожа с моделью Фонга, но реализация отражения у неё выполнена несколько иначе, в результате чего мы можем избежать вышеописанной проблемы. Вместо того, чтобы полагаться на вектор отражения, мы используем так называемый срединный вектор, который является единичным вектором, находящимся ровно по середине между направлением взгляда и направлением света. Чем больше данный срединный вектор приближается к вектору нормали поверхности, тем выше вклад зеркального отражения:

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

Здесь вы можете видеть, что независимо от направления взгляда наблюдателя, угол между срединным вектором и нормалью поверхности никогда не превышает 90 градусов (если только свет не находится гораздо ниже поверхности). Результаты немного отличаются от отражений в модели Фонга, но в целом более визуально правдоподобны, особенно с низкими коэффициентами отражения. Модель затенения Блинна-Фонга использовалась раннее в конвейере с фиксированными функциями OpenGL.

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

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

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

И, собственно, это всё, что нужно знать про модель Блинна-Фонга. Единственное различие между зеркальным отражением Блинна-Фонга и Фонга состоит в том, что теперь мы измеряем угол между нормальным и срединным векторами вместо угла между направлением взгляда и вектором отражения.

С введением срединного вектора у нас больше не будет проблемы зеркального отсечения затенения Фонга. На рисунке ниже показана зеркальная область обоих методов с зеркальным показателем равным 0.5:

Ещё одно тонкое различие между затенением Фонга и Блинн-Фонга заключается в том, что угол между срединным вектором и нормалью поверхности часто меньше угла между вектором направления взгляда и вектором отражения. В результате, чтобы получить визуальные эффекты, подобные затенению Фонга, показатель зеркального блеска должен быть установлен немного выше. Общее эмпирическое правило состоит в том, чтобы установить его между 2х и 4х кратным значениями показателя блеска Фонга.

Ниже приводится сравнение между обеими моделями зеркального отражения с показателем Фонга равным 8.0 и компонентом Блинна-Фонга равным 32.0:

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

Здесь мы использовали простой фрагментный шейдер, который переключается между обычными отражениями Фонга и отражениями Блинна-Фонга:

  Google Drive / Исходный код — Урок №30. Продвинутое освещение в OpenGL

  GitHub / Исходный код — Урок №30. Продвинутое освещение в OpenGL

Нажав клавишу b, программа переключается с модели затенения Фонга на модель Блинна-Фонга и наоборот.


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

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

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

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