Что такое Ambient Occlusion и зачем он нужен.
Наверняка, многие из вас наблюдали в играх настройку «фоновое затенение» (Ambient Occlusion), но, уверен, далеко не все догадываются что это такое и для чего необходимо.
Для начала, предлагаю рассмотреть освещение на фрагменте фотографии ниже:
В данном случае, храм находится в тени, тогда как прямой источник освещения в виде солнца скрыт за облаками, но мы все равно можем легко различить структуру сцены — объем, глубину, взаимосвязь между объектами.
Обусловлено это тем, что даже при рассеянном свете, далеко не все участки поверхностей освещаются равномерно, на какие-то участки падает больше лучей, на какие-то — меньше.
В местах, где на поверхность попадает меньше света из-за блокирования лучей близлежащими объектами — фронтонами, пилястрами и т.д., появляются рассеянные тени, которые привязывают близлежащие объекты друг к другу, а также придают глубины сцене.
Без рассеянных теней освещение выглядит монотонным, плоским и неправдоподобным, также теряется связь между объектами.
В старых играх, без разрушаемых строений, физики объектов и с простой геометрией сцены, для имитации фонового затенения использовали статичные карты освещения — 2D текстуры. Карты освещения заранее подготавливаются в редакторе игры и содержат информацию об освещенности объектов сцены. Данный метод подходит только для статичных сцен и неподвижных объектов, т.к. карты освещения не меняются по ходу игры.
В современных играх карты освещения используются все реже, даже несмотря на то, что в некоторых проектах вроде «Орден: 1886», они дают хорошие визуальные результаты. Обусловлено это тем, что карты освещения высокого разрешения, необходимые для реалистичного отображения детализированной геометрии, занимают большие объемы видеопамяти, ввиду чего, подходят больше для закрытых, относительно небольших игровых сцен, тогда как нынче в моде игры с гигантскими открытыми мирами. Кроме того, карты освещения накладывают ограничения на разрушаемость, физику, изменение освещения сцены и прочие игровые аспекты.
По вышеназванным причинам, в современных играх все чаще целиком отказываются от статичных карт освещения в пользу более динамических и комплексных методов, совместимых с разрушаемостью и подвижными объектами, а также позволяющих легко изменять освещение сцены в режиме реального времени. Одним из таких методов является фоновое затенение в экранном пространстве, о котором мы и будем говорить далее по тексту.
В играх, фоновое затенение симулирует вышеупомянутое преграждение света близлежащими объектами, добавляя в сцену рассеянные тени.В случае растеризации, все объекты выводятся и обрабатываются независимо друг от друга, поэтому просто так АО в трехмерном пространстве геометрии не сделать, а выполнять отдельный проход с трассировкой путей не позволяет производительность текущего железа. По этим причинам, для аппроксимации фонового затенения в играх используется буфер глубины — растровое изображение (буфер кадра) с уже отрисованной сценой, в котором, вместо цвета, в каждом пикселе хранятся значения расстояния от камеры до точки поверхности какого-либо объекта сцены.
Выглядит буфер глубины так, чем темнее цвет, тем ближе пиксель к камере:
Отсюда и название целого класса методов — Screen Space Ambient Occlusion (сокр. SSAO), или фоновое затенение в экранном пространстве.
Существует множество вариаций фонового затенения в экранном пространстве — BTAO (Broad Temporal Ambient Obscurance), LSAO (Line-Sweep Ambient Obscurance), SSBC, HMSSAO, большая часть которых использует небольшое число сэмплов, простые эвристики для устранения артефактов и ориентированы на слабые машины.
Но сегодня речь пойдет о самых передовых и инновационных технологиях фонового затенения на ПК, оптимизированных для работы с большим числом сэмплов и имеющих сложные эвристики для предотвращения графических артефактов, таких технологиях, как HBAO+ (улучшенный Horizon Based Ambient Occlusion ) и VXAO (Voxel Ambient Occlusion).
Для начала рассмотрим простейший случай SSAO. Благодаря буферу глубины, который выступает как 2.5D поле высот, в пиксельном шейдере — программе граф. конвейера, позволяющей изменять цвет пикселей, можно определить насколько тот или иной пиксель сцены затенен близлежащими объектами.
Самый простой способ определить степень затенения в исходной точке объекта (пикселе) — создать тестовые сэмплы с произвольными локациями в пределах заданного радиуса внутри полусферы, после чего сравнить таковые по глубине со значениями пикселей буфера глубины (изображены как серый рельеф на изображениях ниже), если значение сэмпла меньше значения пикселя буфера глубины, то сэмпл находится внутри геометрии, иначе — вне геометрии:
На срезе полусферы выше (вид: поле высот), P — исходная точка объекта (исходный пиксель буфера глубины), n — нормаль в исходной точке, серый рельеф — геометрия (поле высот), представленная значениями пикселей буфера глубины в окрестности точки P, красные квадраты — сэмплы, вносящие вклад в затенение исходного пикселя (близлежащие объекты внутри искомого радиуса), зеленые квадраты — сэмплы, не вносящие вклад в затенение исходного пикселя (пустое пространство).
Затенение в исходной точке тем сильнее, чем больше сэмплов попадает на соседние объекты, сила затенения легко регулируется при помощи доп. коэффициентов.
При большом числе сэмплов можно увеличивать радиус поиска, не жертвуя качеством и стабильностью изображения в динамике, что делает картинку более реалистичной, а переходы в освещении более плавными.
С небольшим числом сэмплов, радиус поиска ограничен, а переходы между поверхностями резкие и неправдопобные.
^^^ Сцена без фонового затенения.
^^^ Сцена с HBAO+ с 32 сэмплами на пиксель
Как можно заметить, сцена с HBAO+ значительно ближе по освещению к фотографии выше, рассеянные тени и плавные переходы тонов дают лучшее представление о структуре сцены, так, благодаря фоновому затенению, становится понятно, что храм стоит на поверхности, также появляется связь между отдельными архитектурными элементами. Более того, с АО, становятся заметны мелкие монотонно освещенные детали, такие как окна.
Наилучшее качество фонового затенения на сегодня обеспечивает HBAO+ и AO методом трассировки лучей в экранном пространстве, но только первый метод достаточно быстрый для использования большого числа сэмплов.
По сравнению с другими методами, такими как SSBC в FarCry 4 с 12 сэмплами на пиксель, HBAO+ с 36 сэмплами обеспечивает значительно более качественное затенение.
Видно, что рассеянные тени реалистичнее с HBAO+, без резких переходов в освещении, свойственных более простым методам. Также обратите внимание на подушки, благодаря большому радиусу поиска с 36 сэмплами, тень не исчезает за подушкой как в случае с 12 сэмплами SSBC. Переключив внимание на другие детали, можно заметить, что стена за шторой справа корректно затеняется с HBAO+ и не затеняется с SSBC, тогда как хорошо освещенная штора слева лишена бандинга и затенена в меньшей степени с HBAO+, который, согласно физически корректной модели, учитывает прямое освещение при затенении.
Консольные методы SSAO зачастую работают с буфером глубины в половинном разрешении, компенсируя недостатки в виде мельтешения пикселей во время движения использованием сэмплов из предыдущего кадра. Данный подход имеет свои недостатки в виде «хвостов» (остаточных следов при движении камеры), лишнего бандинга и ухудшения производительности карт в мульти ГПУ режимах с SLI, т.к. приходится копировать дополнительные буферы между картами.
Существенным недостатком большинства методов фонового затенения в экранном пространстве являются светлые силуэты вокруг персонажей и прочих движущихся объектов.
Этот неприятный артефакт возникает, когда подвижные объекты загораживают статичные. В этом случае невозможно корректно рассчитать затенение статичных объектов, т.к. шейдер работает с 2D буфером глубины, в котором присутствуют пиксели только видимых объектов и только со стороны камеры, тогда как информация об обратной стороне геометрии, перекрытых объектах и объектах не попадающих в камеру отсутствует.
Ультра пресет HBAO+ в Assassin’s Creed: Syndicate решает и эту проблему, рассчитывая фоновое затенение в два прохода. Сначала для статичной части сцены с большим радиусом охвата АО для лучшего затенения крупных деталей строений и техники, затем для подвижных объектов с меньшим радиусом АО для лучшего затенения мелких деталей персонажей, после чего, два буфера с АО комбинируются в один финальный буфер. В результате, подвижные объекты не влияют на корректность затенения статичных объектов на заднем фоне.
Обратите внимание на затенение рядом с массовкой, только в случае Ultra опции HBAO+, рассеянные тени рассчитываются корректно для статичной геометрии за персонажами. С остальными алгоритмами и опциями, АО для статичной геометрии рассчитывается некорректно, а вокруг персонажей возникают светлые ореолы.
Другим существенным недостатком фонового затенения в экранном пространстве является локальность эффекта.
Т.к. шейдер работает с 2D текстурой буфера глубины, обратная сторона объектов в кадре и геометрия вне кадра не оказывают никакого влияния на степень затенения. Радиус поиска в пределах кадра также существенно ограничен производительностью, т.к. с ростом разрешения для покрытия той же площади кадра без ухудшения качества требуется проверять все больше сэмплов на пиксель, что приводит к нелинейному росту сложности.
Исправить эти существенные недостатки помогает VXAO — метод фонового затенения, который конвертирует полигональную трехмерную сцену в воксельную сетку при помощи аппаратных возможностей чипов на архитектурах Максвелл, Паскаль и Вольта, таких как консервативная растеризация и мультипроекция, ускоряющих процесс вокселизации более чем в 3 раза.
После чего, воксельная структура данных, будь то разреженное воксельное октодерево, 3D текстура или что-то еще, используется для высокопроизводительной трассировки конусами. С позиции каждого пикселя экранного буфера глубины трассируется до 16 конусов по всем направлениям трехмерной воксельной сетки.
В результате, даже если стена или потолок не попали в кадр, они по прежнему будут вносить вклад в освещение, обратная сторона крупных объектов также учитывается. На последнем этапе, слой буфера кадра с глобальным затенением после VXAO комбинируется со слоем локального затенения после HBAO+ для обеспечения максимального качества.
Сразу видно, что сцена стала более объемной, под стулом и столом появились рассеянные тени, которые не по силам методам в экранном пространстве из-за ограниченного радиуса охвата и отсутствия информации об обратной стороне геометрии. Освещение в ящиках, на потолке и под досками на полу стало контрастнее, комплекснее и правдоподобнее.
В отличие от методов в экранном пространстве, работающих с 2D буфером глубины, АО в трехмерном пространстве вокселей не зависит от положения камеры относительно поверхностей объектов, поэтому фоновое затенение никуда не пропадает как ни верти камерой. Ну и т.к. это глобальное фоновое затенение, учитывающее всю сцену, воксельный АО не мерцает, не шумит, не исчезает на краях экрана и не производит прочие артефакты свойственные локальному фоновому затенению при небольшом числе сэмплов.
Тем не менее, из-за ограниченного разрешения воксельной сетки, для воспроизведения локального фонового затенения на мелких объектах, таких как камни, трава и т.д., VXAO по прежнему используется совместно с HBAO+.
Забавные картинки напоследок, да, такие артефакты SSАО встречаются в играх сплошь и рядом. Корректная реализация АО сопряжена со множеством трудностей и требует неимоверных усилий.
Если вам понравился пост, в следующей части можно обсудить производительность различных методов фонового затенения.