Как трудится затенение в компьютерных играх

    occlusionexample.jpg

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

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

    d6ff226377bf725c280a25110917df93.gif

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

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

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

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

    SSAO



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

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

    ssao3.jpg

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

    HBAO и HBAO+



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

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

    hbao21.jpg

    HDAO



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

    7d758ebb_1355517972SmtzmJYEeY_7_2_l.png

    VXAO



    С выходом DX12 Nvidia представила принципиально новое тенение — VXAO (Voxel Accelerated Ambient Occlusion). Его суть в том, что оно трудится уже не с пикселями и текселями (то есть 2D-объектами), а с вокселями — аналогом пикселя в 3D. И сейчас мы используем не Z-буфер, а воксельное построение сцены, поэтому алгоритм находится из трех пунктов: вокселизация, постобработка вокселей и трассировка конуса. Вокселизация исполняется путем рендеринга треугольных сеток в трехмерную текстуру, и поэтому ее выработка сильно зависит от общего количества треугольников, размера этих треугольников и численности вызовов рисования, необходимых для их рендеринга. Постобработка объединяет проходы, подобные как очистка, фильтрация и понижающие выборки вокселей, а ее производительность зависит от всеобщего количества вокселей, созданных во время вокселизации. Типичное период после обработки составляет 0,5 — 1,5 мс. И, наконец, намечание конуса выполняется в пространстве экрана, поэтому его производительность зависит от дозволения экрана и скорости затенения. Итоговое качество картинки оказывается в много лучше, чем с HBAO+:

    AO-HBAO-VXAO.jpg

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