затенение ssao что это

Как работает затенение в компьютерных играх

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

С появлением 3D-игр у их создателей серьезно прибавилось проблем: о сглаживании мы уже говорили, также мы говорили и о фильтрации текстур. Теперь же поговорим о еще одном эффекте, который позволяет серьезно улучшить реалистичность картинки — о Ambient Occlusion (AO), или о затенении.

В оптике можно выделить три простых градации освещенности — тень (источник света не виден), полутень (источник света виден частично) и освещенное место (источник света виден полностью). Казалось бы — все просто, рассчитать границы тени и полутени можно в два счета с помощью обыкновенных лучей. Однако полученная в результате картинка наводит на мысль, что мы где-то что-то забыли:
затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.
Таких черных теней не бывает (ну на Земле по крайней мере), так что сразу становится очевидным, что мы забыли — рассеяние света: суть в том, что в реальном времени фотоны могут отражаться от различных поверхностей и в итоге попадать туда, куда напрямую фотоны от источника не долетают: именно поэтому в тени хоть и темнее, чем на свету, но не черным черно. На Земле таким «рассеивателем» фотонов выступает сама атмосфера.

Но тут возникает вопрос — а как это рассчитать-то? Увы — алгоритма, дающего 100% точное рассеяние света в real-time, нет, однако есть множество хорошо приближенных к реальности алгоритмов, отлаженных настолько, что они спокойно используются в видеоиграх.

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

Однако тут мы получаем очередную проблему — отрисовка геометрии происходит постепенно, поэтому заграждающий фактор также в процессе отрисовки может серьезно меняться. Можно, конечно, рассчитать AO на этапе загрузки сцены, но тогда затенение не коснется динамических объектов (персонажей, машин и т.д.) — а это нехорошо. И тут приходит идея использовать для отрисовки затенения экранное пространство (Screen Space), что в итоге выливается в простейший алгоритм AO — SSAO.

SSAO

Этот алгоритм появился еще в Crysis 10 лет назад. Его суть проста: после построения геометрии у нас остается Z-буфер, или буфер глубины, который включает в себя абсолютно всю информацию о геометрии сцены — а значит никаких проблем сделать AO нет.

Хотя, конечно, кого я обманываю — проблемы есть, и самая серьезная — недостаточная производительность современных видеокарт: для того, чтобы получить более-менее неплохую карту затенения, для каждого фрагмента сцены нужно обсчитывать порядка 200-250 направлений, что позволяет «закопать» любой GPU. Поэтому делается хитрее — используется 8-32 «луча», направленные на выбранный фрагмент сцены, которые каждый раз поворачиваются на случайное значение. В итоге получается терпимое качество картинки с не очень большими затратами на расчеты:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

HBAO и HBAO+

Nvidia не была бы Nvidia, если бы не стала развивать затенение дальше, представив в 2008 году HBAO — Horizon Based Ambient Occlusion. От SSAO это затенение отличалось тем, что оно основано на физической модели, где аппроксимируется интеграл освещенности фрагмента сцены со значениями выборки буфера глубины. Итоговое качество оказывается выше SSAO при большом числе выборок, но мы опять же упираемся в производительность. Поэтому HBAO рендерится обычно в более низком разрешении, что приводит к мерцанию картинки.

Проблема мерцания была исправлена в HBAO+ простым методом, который сейчас активно использует Sony в 4К играх на PlayStation 4 Pro: для рассчета HBAO+ используется шахматный рендеринг, то есть для обработки затенения используется часть предыдущего кадра и половина нового: это требует меньше затрат GPU, но при этом позволяет рендерить затенение в исходном разрешении, что и убирает мерцание.

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

HDAO

AMD в стороне не остались, и стали использовать собственное затенение (которое, к слову, также работает и на Nvidia) — HDAO (High Definition AO). Увы — AMD не делится алгоритмом, однако известно, что в его основе лежит Gather4 — технология, которая собирает 4 текселя в один регистр. То есть, как и с HBAO, по сути происходит рендеринг в пониженном разрешении. В итоге, в среднем картинка с HBAO и HDAO сравнима по качеству, но опять же — все достаточно сильно зависит от игры: к примеру, в Far Cry 3 с HDAO трава выглядит красивее:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.
На этом все. Советы для игроков простые: если компьютер хорошо тянет игру без AO, то можно попробовать включить SSAO или HBAO — обычно это снижает fps не более чем на 10%. Если же и с ними производительность отличная — можно попробовать HBAO+ и HDAO. Ну и для самых топовых видеокарт современности можно порекомендовать набирающее обороты VXAO — оно крайне требовательно к ресурсам (в том числе и к видеопамяти), поэтому даже в FHD оно будет доступно лишь пользователям старших Nvidia GTX 900ой и 1000ой линейки, а также владельцам старших AMD RX, Fury и Vega.

Источник

Learn OpenGL. Урок 5.10 – Screen Space Ambient Occlusion

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

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

Ниже представлено сравнение рендера без и с использованием алгоритма AO. Обратите внимание на то, как падает интенсивность фонового освещения в окрестности углов стен и прочих резких изломов поверхности:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Стоит отметить, что алгоритмы расчета AO являются довольно ресурсоемкими, поскольку требуют анализа окружающей геометрии. В наивной реализации можно было бы просто в каждой точке поверхности выпустить множество лучей и определить степень её затенения, но такой подход весьма быстро достигает допустимого для интерактивных приложений предела ресурсоемкости. К счастью, в 2007 году компания Crytek опубликовала работу с описанием собственного подхода в реализации алгоритма фонового затенения в экранном пространстве (Screen-Space Ambient Occlusion, SSAO), который использовался в релизной версии игры Crysis. Подход рассчитывал степень затенения в экранном пространстве, используя лишь текущий буфер глубины вместо реальных данных об окружающей геометрии. Такая оптимизация радикально ускорила алгоритм по сравнению с эталонной реализацией и при этом давала по большей части правдоподобные результаты, что сделало данный подход приближенного расчета фонового затенения стандартом де-факто в индустрии.

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

Очевидно, что качество и реалистичность эффекта прямо зависит от числа сделанных выборок. При малом числе выборок точность алгоритма падает и приводит к появлению артефакта бэндинга (banding) или «полошения» из-за резких переходов между областями с сильно отличающимися коэффициентами затенения. Большое же число выборок просто убивает производительность. Рандомизации ядра выборок позволяет при схожих по качеству результатах несколько снизить число требуемых выборок. Подразумевается переориентация поворотом на случайный угол набора векторов выборок. Однако внесение случайности тут же приносит новую проблему в виде заметного шумового узора, что требует использования фильтров размытия для сглаживания результата. Ниже приведен пример работы алгоритма (автор – John Chapman) и его типичные проблемы: бэндинг и шумовой узор.

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Как видно, заметное полошение из-за малого числа выборок неплохо убирается внесением рандомизации ориентации выборок.

Конкретная реализация SSAO от Crytek обладала узнаваемым визуальным стилем. Поскольку специалисты Crytek использовали сферическое ядро выборки это сказывалось даже на плоских поверхностях типа стен, делая их затененными – ведь половина объема ядра выборки оказывалась погруженной под геометрию. Ниже – скриншот со сценой из Crysis, изображенной в градациях серого на основе значения коэффициента затенения. Здесь хорошо виден эффект «серости»:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Осуществляя выборку из такой полусферы ориентированной по нормали (normal-oriented hemisphere) нам не придется учитывать в расчете коэффициента затенения фрагменты, лежащие под поверхностью прилегающей поверхности. Такой подход убирает излишнее затенение в, в целом, дает более реалистичные результаты. Данном урок будет использовать подход с полусферой и немного доработанный код из блестящего урока по SSAO от John Chapman.

Буфер с исходными данными

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Поскольку SSAO является эффектом, реализующимся в экранном пространстве, то непосредственный расчет возможно выполнить отрендерив полноэкранный квад. Но тогда у нас не будет данных о геометрии сцены. Чтобы обойти такое ограничение, мы осуществим рендер всей необходимой информации в текстуры, которые позже будут использованы в шейдере SSAO для доступа к геометрической и прочей информации о сцене. Если вы внимательно следовали данным урокам, то уже должны узнать в описанном подходе облик алгоритма отложенного затенения. Во многом поэтому эффект SSAO как родной встает в рендер с отложенным затенением – ведь текстуры, хранящие координаты и нормали, уже доступны в G-буфере.

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

Поскольку доступ к пофрагментной информации о координатах и нормалях уже должен быть доступен за счет G-буфера, то фрагментный шейдер стадии обработки геометрии достаточно прост:

Поскольку алгоритм SSAO является эффектом в экранном пространстве, а коэффициент затенения вычисляется на основе видимой области сцены, то есть смысл вести расчеты в видовом пространстве. В данном случае переменная FragPos, полученная из вершинного шейдера, хранит положение именно в видовом пространстве. Стоит удостовериться, что данные о координатах и нормалях хранятся в G-буфере в видовом пространстве, поскольку все дальнейшие расчеты будут осуществляться в нем же.

Существует возможность восстановления вектора положения на основе лишь известной глубины фрагмента и некоторого количества математической магии, что описано, например, у Matt Pettineo в блоге. Это, конечно, требующий бОльших затрат на расчеты способ, однако он избавляет от необходимости хранить данные о положении в G-буфере, что занимает уйму видеопамяти. Однако, ради простоты кода примера, мы оставим этот подход для личного изучения.

Текстура буфер цвета gPosition сконфигурирована следующим образом:

Данная текстура хранит координаты фрагментов и может быть использована для получения данных о глубине для каждой точки из ядра выборок. Отмечу, что текстура использует формат данных с плавающей точкой – это позволит координатам фрагментов не быть приведенными к интервалу [0., 1.]. Также обратите внимание на режим повтора – установлен GL_CLAMP_TO_EDGE. Это необходимо для устранения возможности не нарочно осуществить оверсэмплинг в экранном пространстве. Выход за пределы основного интервала текстурных координат даст нам некорректные данные о положении и глубине.

Далее займемся формированием полусферического ядра выборок и созданием метода случайной его ориентации.

Создание ориентированной по нормали полусферы

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Предполагая радиус полусферы единичным процесс формирования ядра выборки из 64 точек выглядит так:

Здесь мы случайным образом выбираем координаты x и y в интервале [-1., 1.], а координату z – в интервале [0., 1.] (будь интервал таким же, как для x и y, мы бы получили сферическое ядро выборки). Результирующие вектора выборок окажутся ограничены полусферы, поскольку ядро выборки в конечном итоге будет сориентировано вдоль нормали к поверхности.

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

Функция lerp() определена как:

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

Случайный поворот ядра выборки

Итак, внесение случайности в распределение точек ядра выборки позволяет значительно снизить требование к числу этих точек для получения достойного качества эффекта. Можно было бы создать случайный вектор поворота для каждого фрагмента сцены, но это слишком затратно по памяти. Эффективней создать небольшую текстуру, содержащую набор случайных векторов поворота, а затем просто использовать её с установленным режимом повтора GL_REPEAT.

Создадим массив 4х4 и заполним случайными векторами поворота, сориентированными вдоль вектора нормали в касательном пространстве:

Поскольку ядро выровнено вдоль положительной полуоси Z в касательном пространстве, то компонент z оставляем равным нулю – это обеспечит поворот только вокруг оси Z.

Далее создадим текстуру размером также 4х4 и зальем туда наш массив векторов поворота. Обязательно используйте режим повтора GL_REPEAT для тайлинга текстуры:

Что ж, теперь у нас готовы все данные, необходимые для непосредственной реализации алгоритма SSAO!

Шейдер SSAO

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

Поскольку результат работы алгоритма – единственное вещественное число в пределах [0., 1.], то для хранения будет достаточно создать текстуру с единственной доступной компонентой. Именно поэтому в качестве внутреннего формата для буфера цвета ставится GL_RED.

В целом процесс рендера стадии SSAO выглядит примерно следующим образом:

Шейдер shaderSSAO принимает нужные ему текстуры G-буфера как входные данные, а также шумовую текстуру и ядро выборки:

Обратите внимание на переменную noiseScale. Наша маленькая текстура с шумом должна быть затайлена по всей поверхности экрана, но поскольку текстурные координаты TexCoords заключены в пределах [0., 1.] этого не произойдет без нашего вмешательства. В этих целях мы вычисляем множитель для текстурных координат, который находится как отношение размера экрана к размеру шумовой текстуры:

Поскольку при создании шумовой текстуры texNoise мы установили режим повтора в GL_REPEAT, то теперь она будет повторяться множество раз на поверхности экрана. Имея на руках величины randomVec, fragPos и normal мы можем создать матрицу TBN трансформации из касательного пространства в видовое:

Используя процесс Грамма-Шмидта мы создаем ортогональный базис, случайно наклоненным в каждом фрагменте на основе случайного значения randomVec. Важный момент: поскольку в данном случае нам неважно, чтобы матрица TBN была точно сориентирована вдоль поверхности треугольника (как в случае с parallax mapping’ом, прим. пер.), то нам не нужны предрасчитанные данные о касательных и бикасательных.

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

Пока звучит запутанно, разберем это по шагам:

Здесь kernelSize и radius являются переменными, контролирующими характеристики эффекта. В данном случае они равны 64 и 0.5 соответственно. На каждой итерации мы переводим вектор ядра выборки в видовое пространство. Далее прибавляем к полученному значению смещения выборки в видовом пространстве значение положения фрагмента в видовом пространстве. При этом значение смещения умножается на переменную radius, которая управляет радиусом ядра выборки эффекта SSAO.

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

После преобразования в клиповое пространство мы вручную осуществляем перспективное деление простым делением компонент xyz на w компоненту. Полученный вектор в нормализованных координатах устройства (NDC) переводится в интервал значений [0., 1.] дабы его можно было использовать как текстурные координаты:

Используем компоненты xy вектора sample для выборки из текстуры положений G-буфера. Получим значение глубины (z компоненты), соответствующее вектору выборки при взгляде с позиции наблюдателя (это первый не заслоненный видимый фрагмент). Если при этом полученная глубина выборки оказывается больше, чем сохраненная глубина, то мы увеличиваем коэффициент затенения:

Обратите внимание на смещение bias, которое добавляется к исходной глубине фрагмента (в примере установлена в 0.025). Это смещение не всегда является обязательным, но наличие переменной позволяет управлять тем, как выглядит эффект SSAO, а также, в определенных ситуациях, убирает проблемы с рябью в затененных областях.

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

Также мы применяем функцию GLSL smoothstep(), которая реализует плавную интерполяцию третьего параметра в пределах между первым и вторым. При этом возвращая 0, если третий параметр меньше или равен первому, либо 1, если третий параметр больше либо равен второму. Если разница глубин оказывается в пределах radius, то её величина будет плавно сглажена в интервале [0., 1.] в соответствии с данной кривой:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

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

Для сцены с лежащим знакомым нам нанокостюмом, выполнение SSAO шейдера дает следующую текстуру:

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

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

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

Размытие фонового затенения

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

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Итого у нас на руках есть текстура с данными фонового затенения для каждого фрагмента на экране – все готово для стадии финального сведения изображения!

Применение фонового затенения

Этап применения коэффициента затенения в итоговом расчете освещения на удивление прост: для каждого фрагмента достаточно просто умножить значение фоновой составляющей источника света на коэффициент затенения из подготовленной текстуры. Можно взять готовый шейдер с моделью Блинна-Фонга из урока по отложенному затенению и немного его подправить:

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

затенение ssao что это. затенение ssao что это фото. картинка затенение ssao что это. смотреть фото затенение ssao что это. смотреть картинку затенение ssao что это.

Полный исходный код лежит здесь.

Проявление эффекта SSAO сильно зависит от параметров типа kernelSize, radius и bias, зачастую их тонкая подстройка – само собой разумеющееся занятие художника при проработке той или иной локации/сцены. Нет каких-то «лучших» и универсальных сочетаний параметров: для одних сцен хорош малый радиус ядра выборки, другие выигрывают от увеличенного радиуса и числа выборок. В примере используется 64 точки выборки, что, откровенно говоря, избыточно, но вы всегда можете отредактировать код и посмотреть, что получится при меньшем числе выборок.

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

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

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

Источник

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

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