Являетесь ли вы консольным или ПК-геймером, вы, вероятно, в какой-то момент слышали об окружающей окклюзии экранного пространства. Это вдвойне важно для геймеров на ПК, когда они возятся с настройками графики для достижения оптимальной производительности на любой конкретной установке. Проблема в том, что не каждая игра точно описывает, что делает SSAO. Наше руководство объясняет окклюзию окружающего пространства экрана и ее влияние на визуальную точность.
Что делает SSAO?
Проще говоря, окружающее затенение экранного пространства добавляет окружающее затенение или участки тени к различным объектам, находящимся в игровой сцене. Окружающее освещение или затенение относится к любому непрямому или естественному освещению, влияющему на сцену. Представьте себе темные пятна в складках простыни или тень под бутылкой с водой. Возможно, вы даже заметите слабую тень под подставкой для телевизора.
С этими тонкими элементами освещения можно обращаться по-разному. С момента появления графических процессоров с поддержкой RTX, а также PS5 и Xbox Series X/S в некоторых играх использовалась трассировка лучей для имитации окружающего затенения. Окклюзия окружающего пространства экрана, однако, использует информацию о пространстве экрана, чтобы определить, как окружающее затенение распределяется по сцене.
Disable DOF, Ambient Occlusion and Settings Skyrimprefs ini for ENB Skyrim SE
Изображение через Nvidia
Это имеет свои пределы. Все, что не находится в поле зрения камеры, не будет учитываться при таком подходе к освещению. Возьмите любую игру с SSAO и медленно перемещайте камеру до тех пор, пока объект с фоновым затенением едва не окажется вне поля зрения. Вы можете заметить, что тени появляются и исчезают по мере того, как игроку становится видна большая часть этого объекта. Это элемент экранного пространства пространственной окклюзии экранного пространства.
С чего началось SSAO?
Оригинальный Crysis 2007 года был пионером вышеупомянутого сеттинга. Это первая коммерчески выпущенная видеоигра, в которой используется окклюзия окружающего пространства на экране. В то время как Crysis была очень требовательной игрой для ПК, вскоре после этого SSAO добралась до консолей. Элементарные реализации были замечены еще в 2008 году в таких играх, как Gears of War 2.
В то время как качество варьировалось в зависимости от названия, затемнение окружающего пространства на экране становилось все более распространенным явлением по мере того, как поколение PS3 и Xbox 360 изнашивалось. Он по-прежнему используется по сей день во многих играх AAA-класса, включая Resident Evil Village на консолях последнего поколения и в режимах без трассировки лучей на консолях текущего поколения.
Источник: nexusmod.ru
Screen space ambient occlusion с учетом нормалей и расчет одного отражения света.
Фоновое освещение — это фиксированная световая константа, добавляемая к общему освещению сцены для имитации рассеивания света. В реальном мире свет рассеивается во всех направлениях и с различной интенсивностью, поэтому опосредованно освещенные части сцены также должны иметь различную интенсивность освещения.
Одним из видов аппроксимации непрямого освещения является фоновое затенение (сокр. «AO» от англ. «Ambient Occlusion»), которое пытается имитировать непрямое освещение путем затемнения складок, отверстий и поверхностей, расположенных близко друг к другу. Эти области в значительной степени перекрыты окружающей геометрией, из-за чего у лучей света становится меньше шансов выбраться наружу, а поэтому подобные области кажутся темнее. Взгляните на углы и складки вашей комнаты — вы увидите, что свет в них кажется немного темнее.
Ниже приведен пример изображения сцены с использованием метода фонового затенения и без него. Обратите внимание, что между складками и в углах (фоновое) освещение выглядит более темным:
Хотя рассматриваемый эффект и не бросается в глаза так явно, как остальные, но изображение с фоновым затенением действительно выглядит намного более реалистичным из-за присутствия небольших, но при этом не менее существенных деталей освещения, придающих всей сцене гораздо большее ощущение глубины.
Алгоритмы расчета AO являются довольно ресурсоемкими, поскольку они должны учитывать окружающую геометрию. На первый взгляд кажется, что для каждой точки в пространстве можно было бы испускать большое количество лучей, чтобы определить величину её фонового затенения, но этот процесс очень быстро упрется в ограничения производительности для решений, работающих в реальном времени. В 2007 году компания Crytek в своей игре под названием Crysis использовала методику, известную как SSAO (от англ. «Screen-Space Ambient Occlusion»). Вместо реальных геометрических данных для определения величины фонового затенения, вышеупомянутый метод задействует буфер глубины сцены в координатах экранного пространства. По сравнению с обычным AO рассматриваемый подход является невероятно быстрым в вычислительном плане и дает правдоподобные результаты, что делает его де-факто стандартом для моделирования фонового затенения в реальном времени.
Основы метода SSAO довольно просты: для каждого фрагмента на «экранном прямоугольнике» мы вычисляем коэффициент затенения, основанный на окружающих фрагмент значениях глубины. Затем данный коэффициент используется для уменьшения или обнуления компонента затенения фрагмента. Коэффициент затенения получают путем взятия нескольких выборок значений глубины из некоторой сферической окрестности (ядра выборки) заданного фрагмента и сравнения значения в каждой точки выборки с текущим значением глубины фрагмента. Количество точек выборок, имеющих более высокое значение глубины, чем глубина фрагмента, представляет собой коэффициент затенения.
Как вы можете видеть из рисунка, каждая точка выборки глубины (серого цвета), находящаяся внутри некоторого геометрического объекта, вносит свой вклад в итоговое значение коэффициента затенения; чем больше точек выборок окажутся внутри объекта(ов), тем меньше фонового освещения должен в конечном итоге получить фрагмент.
Становится понятно, что качество и точность эффекта напрямую связаны с количеством точек выборок, которые мы используем. Если их слишком мало, то точность метода резко снижается, и мы получаем артефакт в виде некоторой полосатости/сегментации изображения, называемый бандингом (от англ. «banding»); если же точек выборок слишком много, то падает производительность алгоритма. Мы можем уменьшить требование к используемому количеству выборок, введя некоторую случайность в ядро выборки. Произвольно вращая ядро выборки каждого фрагмента, мы можем получить высококачественные результаты с гораздо меньшим количеством непосредственно самих выборок. Однако данная случайная составляющая вносит заметную картину шума, которую нам придется исправить, применив к полученным результатам размытие. Ниже приведено изображение (любезно предоставленное John Chapman), демонстрирующее эффект бандинга и влияние случайной составляющей на конечный результат:
Как вы можете видеть на картинке слева, при использовании SSAO с недостаточным количеством точек выборки мы получаем заметный эффект бандинга. Вводя некоторую случайную составляющую поворота и применяя размытие к конечному результату, мы полностью убираем эффект бандинга.
Метод SSAO, разработанный компанией Crytek, имел определенный узнаваемый визуальный стиль. Поскольку формой использованного ядра выборки была сфера, то плоские стенки выглядели серыми, поскольку половина точек выборки из ядра в конечном итоге оказывалась внутри окружающей геометрии. Ниже представлено SSAO-изображение Crysis в режиме «градации серого», на котором наглядно изображен описываемый эффект:
По этой причине мы будем использовать не сферическое ядро, а полусферическое ядро, ориентированное вдоль вектора нормали поверхности.
Производя выборки внутри изображенной выше нормально-ориентированной полусферы, мы, при вычислении коэффициента затенения, избавляем себя от расчетов составляющей затенения, вносимого фрагментами, лежащими ниже прилегающей поверхности. Благодаря этому получаются, как правило, более реалистичные результаты.
Минимальные и максимальные графические настройки World of Tanks
World of Tanks
имеет очень широкий спектр графических настроек, чтобы удовлетворить максимум возможных игровых конфигураций. Но в то же время, игра достаточно требовательная к железу, ведь на максимальных настройках графики и высоких разрешениях системные требования далеко не умеренные, и потребуется достаточно мощный компьютер для комфортной игры в
WoT
, особенно с установленным паком HD-текстур.
Разница между минимальными и максимальными графическими настройками:
Как видно из скриншотов, различия просто колоссальные. На максимальных настройках в разы лучше детализация текстур, качество картинки и четкость изображения, а все объекты получают дополнительные детали. В общем, здесь всё видно даже невооружённым взглядом.
Что такое тесселяция?
Тесселяция может сделать круг из восьмиугольника, или рельефную древесную кору из гладкого бревна. Уже готовые полигоны разбиваются на несколько более мелких основываясь на некоторых параметрах и текстурах объекта, за счет этого, там где это может помочь форма объектов становиться более законченной.
По идее она не должна особо сказаться на производительности, но это зависит от того как часто она используется в игре. Каждый движок игры работает немного по своему, а также разработчики игры могут определить где она будет использоваться а где нет. Например в той же GTA 5 ее можно заметить в основном только на деревьях, на других объектах она не используется. Так что эту настройку следует выставлять опытным путем.
Какое качество теней устанавливать в игре?
Тени очень прожорливая составляющая красивой картинки и в большинстве игр разница между высокими и низкими настройками очень большая. Также и большая разница в нагрузке на видеокарту, ведь для расчета точных и красивых теней требуется очень большое количество ресурсов видеосистемы вашего ПК.
Особенно сильно влияет это параметр при динамическом освещении, а в современных играх практически любой источник света является динамическим. Также необходимо отметить и про глобальное освещение, оно тесно связано с настройками теней.
Так что если частота кадров очень низкая то снижайте настройки теней и детализации, так как они взаимосвязаны между собой.
Мягкие тени
Особенно это касается мягких теней, которые мало того что очень зависят от качества детализации объекта, так и еще просчитываются несколькими лучами, что создает огромную нагрузку на видеосистему и на слабых видеокартах лучше не использовать мягкие тени вообще.
Виды сглаживая в играх. Какое сглаживание выбрать в игре?
Виды сглаживания бывают разные, их технологии совершенствуются, комбинируются но в целом они делятся на две большие подгруппы:
Первая подгруппа подразумевает изначальное увеличение изображения и последующее сжатие его до нужного размера. В эту группу относиться, например MSAA. Разумеется нагрузка при таком виде сглаживая сильно возрастает.
Здесь самым прожорливым с точки зрения видеокарты является NVIDIA TXAA, который учитывает результаты сглаживания предыдущих кадров.
При таком методе помимо уменьшения нагрузки еще и пропадают искажения, появляющиеся из за того, что обычно для каждого кадра сглаживание просчитывается с нуля.
Вторая группа основывается на обработке уже готового изображения, что гораздо менее ресурсозатратно чем первый способ. Для примера FXAA, но такой тип сглаживая работает с конечным изображение и не может знать где какие должны быть грани, именно поэтому это сглаживание может превратить картинку в мыло, но в некоторых играх такой тип сглаживания работает более менее нормально.
Источник: driverunpaid.ru
SSLR: Screen Space Local Reflections в AAA-играх
Привет, друг! В этот раз я опять подниму вопрос о графике в ААА-играх. Я уже разобрал методику HDRR (не путать с HDRI) тут и чуть-чуть поговорил о коррекции цвета. Сегодня я расскажу, что такое SSLR (так же известная как SSPR, SSR): Screen Space Local Reflections. Кому интересно — под кат.
Введение в Deferred Rendering
Для начала введу такое понятие как Deferred Rendering (не путать с Deferred Shading, т.к. последнее относится к освещению). В чем суть Deferred Rendering? Дело в том, что все эффекты (такие как освещение, глобальное затенение, отражения, DOF) можно отделить от геометрии и реализовать эти эффекты как особый вид постпроцессинга.
К примеру, что нужно, чтобы применить DOF (Depth Of Field, размытие на дальних расстояниях) к нашей сцене? Иметь саму сцену (Color Map) и иметь информацию о позиции текселя (другими словами на сколько пиксель далеко от камеры). Далее — все просто. Применяем Blur к Color Map, где радиус размытия будет зависеть от глубины пикселя (из Depth Map).
И если взглянуть на результат — чем дальше объект, тем сильнее он будет размыт. Так что же делает методика Deferred Rendering? Она строит так называемый GBuffer, который, обычно, в себя включает три текстуры (RenderTarget):
- Color map (информация о диффузной составляющий или просто цвет пикселя)
- Normal map (информация о нормали “пикселя”)
- Depth map (информация о позиции “пикселя”, тут храним только глубину)
В случае с Color map, Normal map вроде все понятно, это обычные Surface.Color текстуры: пожалуй, за исключением того, что вектор нормали может лежать в пределах [-1, 1] (используется простая упаковка вектора в формат [0, 1]).
А вот ситуация с Depth map становится непонятной. Как же Depth map хранит в себе информацию о позиции пикселя, да еще и одним числом? Если говорить сильно упрощенно, трансформация примитива:
float4 vertexWVP = mul(vertex, World*View*Projection);
Дает нам экранные координаты:
float2 UV = vertexWVP.xy;
И некоторую информацию о том, насколько “далеко” от камеры пиксель:
float depth = vertexWVP.z / vertexWVP.w;
Исходя из этого UV нам не нужен, т.к. при рисовании обычного квада на весь экран он и так известен. Поэтому стоит хранить в карте глубины не позицию пикселя, а только глубину.
В дальнейшем мы сможем реконструировать позицию пикселя очень простым способом:
float3 GetPosition(float2 UV, float depth) < float4 position = 1.0f; position.x = UV.x * 2.0f — 1.0f; position.y = -(UV.y * 2.0f — 1.0f); position.z = depth; //Transform Position from Homogenous Space to World Space position = mul(position, InverseViewProjection); position /= position.w; return position.xyz; >
Напомню, что для построения GBuffer необходима такая методика как MRT (Multiple Render Targets), которая рисует модель сразу в несколько Render Target (причем в каждом RT содержится разная информация). Одно из правил MRT — размерность всех Render Target должна быть одинаковой. В случае Color Map, Normal Map — Surface.Color: 32-ух битная RT, где на каждый канал ARGB приходится по 8 бит, т.е. 256 градаций от 0 до 1.
Благодаря такому подходу мы можем применять сложные эффекты к любой геометрии, например самый популярный Screen Space эффект: SSAO (Screen Space Ambient Occlusion). Этот алгоритм анализирует буферы глубины и нормали, считая уровень затенения. Весь алгоритм я описывать не буду, он уже описывался на хабре, скажу лишь то, что задача алгоритма сводится к трассировки карты глубины: у нас есть набор случайных векторов, направленных из считаемого “пикселя” и нам нужно найти кол-во пересечений с геометрией.
Пример эффекта (слева без SSAO, справа с SSAO):
Так же Deferred Shading является Screen Space эффектом. Т.е. для каждого источника света на экране (без всяких оптимизаций) мы рисуем квад в режиме Additive в так называемый RenderTarget: Light Map. И зная мировую позицию “пикселя”, его нормаль, позицию источника света — мы можем посчитать освещенность этого пикселя.
Пример Deferred Shading (освещение выполнено отложено, после отрисовки геометрии):
Достоинства и проблемы Screen Space эффектов
Самый главный плюс Screen Space эффектов — независимость сложности эффекта от геометрии.
Самый главный минус — локальность всех эффектов. Дело в том, что мы постоянно будем сталкиваться с Information Lost, во многих случаях это сильно зависит обзора, поскольку SSE зависит от смежных глубин текселей, которые могут быть сгенерированы любой геометрией.
Ну и стоит отменить, что Screen Space эффекты выполняются полностью на GPU и являются пост-процессингом.
Наконец SSLR
После всей теории мы подошли к такому эффекту, как Screen Space Local Reflections: локальные отражения в экранном пространстве.
Для начала разберемся с перспективной проекцией:
Горизонтальный и вертикальный угол зрения задается FOV (обычно 45 градусов, я предпочитаю 60 градусов), в виртуальной камере они разные т.к. учитывается еще и Aspect Ratio (соотношение сторон).
Окно проекции (там, где мы оперируем UV-space данными) — это, что мы видим, на то мы проецируем нашу сцену.
Передняя и задняя плоскости отсечения это соответственно Near Plane, Far Plane, задаются так же в проекцию как параметры. Делать в случае Deferred Rendering слишком большим значением Far Plane стоит, т.к. точность Depth Buffer сильно упадет: все зависит от сцены.
Теперь, зная матрицу проекции и позицию на окне проекции (а так же глубину) для каждого пикселя мы вычисляем его позицию следующим образом:
float3 GetPosition(float2 UV, float depth) < float4 position = 1.0f; position.x = UV.x * 2.0f — 1.0f; position.y = -(UV.y * 2.0f — 1.0f); position.z = depth; position = mul(position, InverseViewProjection); position /= position.w; return position.xyz; >
После нам нужно найти вектор взгляда на этот пиксель:
float3 viewDir = normalize(texelPosition — CameraPosition);
В качестве CameraPosition выступает позиция камеры.
И найти отражение этого вектора от нормали в текущем пикселе:
float3 reflectDir = normalize(reflect(viewDir, texelNormal));
Далее задача сводится к трассировке карты глубины. Т.е. нам нужно найти пересечение отраженного вектора с какой-либо геометрией. Понятное дело, что любая трассировка производится через итерации. И мы в них сильно ограниченны.
Т.к. каждая выборка из Depth Map стоит времени. В моем варианте мы берем некоторое начальное приближение L и динамически меняем его исходя из расстояния между нашим текселем и позицией, которую мы “восстановили”:
float3 currentRay = 0; float3 nuv = 0; float L = LFactor; for(int i = 0; i < 10; i++) < currentRay = texelPosition + reflectDir * L; nuv = GetUV(currentRay); // проецирование позиции на экран float n = GetDepth(nuv.xy); // чтение глубины из DepthMap по UV float3 newPosition = GetPosition2(nuv.xy, n); L = length(texelPosition — newPosition); >
Вспомогательные функции, перевод мировой точки на экранное пространство:
float3 GetUV(float3 position) < float4 pVP = mul(float4(position, 1.0f), ViewProjection); pVP.xy = float2(0.5f, 0.5f) + float2(0.5f, -0.5f) * pVP.xy / pVP.w; return float3(pVP.xy, pVP.z / pVP.w); >
После завершения итераций мы имеет позицию “пересечения с отраженной геометрией”. А наше значение nuv будет проекцией этого пересечения на экран, т.е. nuv.xy – это UV координаты в экранном нашем пространстве, а nuv.z это восстановленная глубина (т.е. abs(GetDepth(nuv.xy)-nuv.z) должен быть очень маленьким).
В конце итераций L будет показывать расстояние отраженного пикселя. Последний этап — собственно добавление отражения к Color Map:
float3 cnuv = GetColor(nuv.xy).rgb; return float4(cnuv, 1);
После компиляции шейдера (отражения) мы получим следующую картину (Color Map из GBuffer + результат шейдера SSLR):
Не густо. И тут стоит еще раз напомнить, что Space-Screen эффекты это сплошной Information Lost (примеры выделены в красные рамки).
Дело в том, что если вектор отражения выходит за пределы Space-Screen – информация о Color-карте становится недоступной и мы видим Clamping нашего UV.
Чтобы частично исправить эту проблему, можно ввести дополнительный коэффициент, который будет отражать “дальность” отражения. И далее по этому коэффициенту мы будем затенять отражение, проблема частично решается:
L = saturate(L * LDelmiter); float error *= (1 — L);
Результат, отражение умноженное на error (попытка убрать артефакт SSLR — information lost):
Уже лучше, но мы замечаем еще одну проблему, что будет, если вектор отразится в направлении камеры? Clamping’а UV происходить не будет, однако, несмотря на актуальность UV (x > 0, y > 0, x < 1, y < 1) он будет неверным:
Эту проблему так же можно частично решить, если как-нибудь ограничить углы допустимых отражений. Для этого идеально подходит фишка с углами от эффекта Френеля:
float fresnel = dot(viewDir, texelNormal);
Чуть-чуть модифицируем формулу:
float fresnel = 0.0 + 2.8 * pow(1+dot(viewDir, texelNormal), 2);
Значения Френеля, с учетом Normal-маппинга (значения fresnel-переменной для SSLR-алгоритма):
Те области, которые отражаются в “камеру” будут черными, и их мы не учитываем (взамен можно сделать fade в кубическую текстуру).
Отражение, умноженное на error и fresnel (попытка удалить большую часть артефактов SSLR):
Кстати, значение Fresnel стоит лимитировать по какому-либо параметру, т.к. из-за “шероховатости” нормалей значение будет на порядок больше единицы (или другого числа-лимитера).
И завершающий этап сегодняшний статьи — это размытие отражений, т.к. идеальное отражение только у зеркала. Степень размытия можно считать как 1-error (чем дальше отраженный пиксель — тем сильнее размыт). Это будет своеобразный вес размытия и хранить его можно в альфа-канале RT-отражений.
Результат (финальное изображение с убранными артефактами и с размытыми отражениями):
Заключение
Так же, стоит добавить некоторую информацию об отражающей способности: насколько четкое отражение, насколько поверхность вообще способна отражать, в те места где SSLR не работает — добавить статическое отражение кубической текстуры.
Конечно, Space-Screen эффекты не являются честными, и разработчики стараются скрыть артефакты, но сейчас в реалтайме подобное (при сложной геометрии) сделать невозможно. А без подобных эффектов игра начинает выглядеть как-то не так. Я описал общую методику SSLR: основные моменты из шейдера я привел. Код, к сожалению, прикрепить не могу, т.к. в проекте слишком много зависимостей.
Удачных разработок! 😉
- Разработка игр
- Алгоритмы
Источник: habr.com