В чем разница между PBR и SSR?
Я очень новичок в разработке игр, и я пытался понять разницу между отражением пространства экрана и физическим рендерингом.
Я читал о PBR, и из того, что я понимаю, он пытается имитировать, как свет отражается в реальной жизни, то есть он обычно разделяется на два компонента, зеркальный и рассеянный, в зависимости от типа материала.
Что касается SSR, пожалуйста, поправьте меня, если я ошибаюсь, это то, как отражения выглядят на поверхности.
Если мое понимание ССР верно, то не совпадают ли они? Я имею в виду, не то, как отражения выглядят на поверхности, зависит от шероховатости поверхности и т. Д. Это будет влиять на то, сколько света отражено и сколько диффузно отражено. Опять же, пожалуйста, поправьте меня, где я не прав
Физический рендеринг
Вы на правильном пути, когда говорите: «Он пытается имитировать, как свет отражается в реальной жизни, то есть он обычно разделяется на два компонента, зеркальный и рассеянный, в зависимости от типа материала».
Но мы уже давно моделируем материалы с зеркальным отражением в играх и компьютерной графике. Хитрость в том, что мы привыкли обрабатывать эти вещи как полностью независимые — изменение зеркальности не изменило диффузию:

Это пример затенения Фонга из вики Blender . Вы можете видеть, что он предлагает два параметра зеркальной интенсивности и зеркальной твердости, и эти параметры только изменяют белесую часть отражения. Голубое рассеянное отражение совсем не меняется.
То, как игры использовали бы это — художник должен был бы вручную настраивать эти значения для каждого материала, пока он не «выглядел правильно». Поскольку «зеркальная твердость» не является реальным физическим свойством материалов, которое мы можем точно измерить, это должно было быть сделано на глаз.
Этот метод немного хрупкий. Когда вы меняете освещение (скажем, динамический объект, движущийся по разным областям, или в среде с временем суток и погодой), оно может выглядеть слегка неправильно — слишком ярким или слишком темным — поскольку условия просмотра не совпадают с те его зеркальные параметры были настроены для.
Войдите в Physical-Based Rendering, которая является попыткой обосновать наши описания материалов более объективными, измеримыми свойствами реальных поверхностей. Одним из наиболее очевидных свойств является сохранение энергии — более грубая поверхность будет рассеивать свет диффузно, а более гладкая / более металлическая поверхность будет отражать свет более прямо, но это тот же источник света, из которого они оба черпают свет. Таким образом, при прочих равных условиях, когда мы делаем материал более блестящим, рассеянный компонент должен стать темнее:

Этот пример взят из статьи Marmoset, объясняющей PBR, изначально предоставленный Syntac_
Физическое рендеринг — это больше, чем энергосбережение, но это, вероятно, самый явный признак того, что вы работаете с физически основанной системой.
Сохраняя модели отражения аналогично тому, как материалы работают в реальной жизни, мы уменьшаем потребность в факторах выдумки и субъективности художника, чтобы реальные материалы, такие как дерево, бетон или кожа, выглядели настоящими в самых разных условиях освещения.
Обратите внимание, что другой ответ описал это в терминах непрямого освещения от света, отражающегося от других объектов в сцене. В то время как многие системы освещения, которые используют физические модели, также включают в себя инструменты для моделирования, это обычно известно под отдельным названием Global Illumination . Это эффект, при котором одна сторона диффузной головки на этом изображении выглядит зеленой, освещенной светом, отражающимся от зеленой стены:

Отражение в пространстве экрана
В то время как PBR пытается смоделировать, как материал отражает свет, Screenspace Reflection пытается уловить то, что отражается — в частности, для блестящей зеркальной поверхности, что я должен увидеть в отражении?
Опять же, это относительно недавний метод рендеринга, который, вероятно, наиболее понятен в отличие от того, как игры делали это раньше:
Рендеринг с переворотом — обычный для водных плоскостей или плоских зеркал, мы буквально рендерим всю отраженную геометрию во второй раз, отражая поперек плоскости отражающей поверхности. Это дает высококачественные отражения (полная детализация, объекты, соприкасающиеся с поверхностью, совпадают с их отражениями), но работает правильно только для плоских поверхностей. Чем более волнистая или неровная поверхность, тем меньше она ведет себя как реальные отражения, которые должны искажать или размыть сложными способами.
Кубические карты — давайте сохраним цвет, который будет виден любому лучу обзора, исходящему из их центральной точки. Динамически визуализируя карты куба из выбранных точек сцены, мы можем оценить, какой цвет должен отражаться от любой произвольно изогнутой поверхности. Проблема в том, что карта куба является полностью правильной только в ее центральной точке — поскольку точка, где мы моделируем отражение, перемещается по сцене, она должна увидеть некоторый параллакс, которого нет на карте куба. Это означает, что объекты не склонны выравниваться со своими отражениями.
Отражение экранного пространства пытается устранить эти ограничения, используя саму визуализированную сцену в качестве источника информации об отражении. Он излучает отраженный луч зрения, используя глубину сцены, пока не пересечет что-то в визуализированной сцене.

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

Вы можете видеть в этом примере отражения в пространстве экрана , впечатление может быть очень убедительным, хотя небольшие ошибки заметны (см. Отражение нижних сторон кубов, которые не видны в визуализированном кадре и поэтому просто смазывают и повторяют смежные пиксели, или отверстия в отражении правой зеленой занавески рядом с цветочным горшком и в нижней части экрана, где лучевая маркировка не смогла найти правильные отраженные пиксели). Обычно этот метод используется для умеренно блестящих / слегка шероховатых поверхностей, чтобы случайная ошибка была менее заметной.
Отражение (компьютерная графика)
Отражение в компьютерной графике используется для имитации отражающих объектов, таких как зеркала и блестящие поверхности.
Точные отражения могут быть достигнуты, например, с помощью средства визуализации трассировки лучей, если проследить луч от глаза к зеркалу, а затем вычислить, откуда он отражается, и продолжить процесс до тех пор, пока не будет обнаружена поверхность или не будет найдена неотражающая поверхность. Приблизительные отражения обычно можно вычислить быстрее, используя такие методы, как отображение среды . Отражение на блестящей поверхности, такой как дерево или плитка, может добавить фотореалистичных эффектов 3D-рендерингу .
СОДЕРЖАНИЕ
Подходы к рендерингу отражения [ править ]
![]()
Для визуализации отражений среды существует множество методов, которые различаются точностью, вычислительной сложностью и сложностью реализации. Возможна также комбинация этих техник.
Алгоритмы рендеринга порядка изображений , основанные на трассировке лучей света, такие как трассировка лучей или трассировка пути , обычно вычисляют точные отражения на общих поверхностях, включая множественные отражения и самоотражения. Однако эти алгоритмы, как правило, по-прежнему слишком дороги в вычислительном отношении для рендеринга в реальном времени (даже несмотря на то, что существует специализированное аппаратное обеспечение, такое как Nvidia RTX ), и требуют другого подхода к рендерингу по сравнению с обычно используемой растеризацией .
Отражения на плоских поверхностях, таких как плоские зеркала или водные поверхности, можно просто и точно вычислить в реальном времени с помощью двухпроходного рендеринга — один для зрителя, второй для просмотра в зеркале, обычно с помощью буфера трафарета . [1] Некоторые старые видеоигры использовали трюк для достижения этого эффекта с помощью рендеринга за один проход, помещая всю зеркальную сцену за прозрачную плоскость, представляющую зеркало. [2]
Отражения на неплоских (криволинейных) поверхностях более сложны для рендеринга в реальном времени. Основные используемые подходы включают:
-
(например, отображение куба ): метод, который широко использовался, например, в видеоиграх, предлагая приближение отражения, которое в основном достаточно для глаза, но не имеет самоотражений и требует предварительной визуализации карты среды. [3] : 174 Точность можно повысить, используя пространственный массив карт среды вместо одной. (SSR): более дорогой метод , что следы отражения лучей в пространстве экрана (в отличие от мирового пространства, например , в режиме трассировки лучей). Это делается для каждого визуализированного пикселя отраженной поверхности с использованием нормали к поверхности и глубины сцены. Недостатком является то, что объекты, не захваченные в визуализированном кадре, не могут появляться в отражениях, что приводит к неразрешенным пересечениям и неполному отражению изображения. [4]
Типы отражения [ править ]
— Полированное отражение — это невозмущенное отражение, подобное зеркалу или хромированной поверхности.
— Размытое отражение означает, что крошечные случайные неровности на поверхности материала делают отражение нечетким.
— Отражение становится металлическим, если блики и отражения сохраняют цвет отражающего объекта.
— Этот термин можно использовать неправильно: иногда это параметр, противоположный размытому (например, когда «глянцевитость» имеет низкое значение, отражение размытое). Иногда этот термин используется как синоним «размытого отражения». Глянцевый, используемый в этом контексте, означает, что отражение действительно размыто.
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 хранит в себе информацию о позиции пикселя, да еще и одним числом? Если говорить сильно упрощенно, трансформация примитива:
Дает нам экранные координаты:
И некоторую информацию о том, насколько “далеко” от камеры пиксель:
Исходя из этого UV нам не нужен, т.к. при рисовании обычного квада на весь экран он и так известен. Поэтому стоит хранить в карте глубины не позицию пикселя, а только глубину.
В дальнейшем мы сможем реконструировать позицию пикселя очень простым способом:
Напомню, что для построения 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 сильно упадет: все зависит от сцены.
Теперь, зная матрицу проекции и позицию на окне проекции (а так же глубину) для каждого пикселя мы вычисляем его позицию следующим образом:
После нам нужно найти вектор взгляда на этот пиксель:
В качестве CameraPosition выступает позиция камеры.
И найти отражение этого вектора от нормали в текущем пикселе:
Далее задача сводится к трассировке карты глубины. Т.е. нам нужно найти пересечение отраженного вектора с какой-либо геометрией. Понятное дело, что любая трассировка производится через итерации. И мы в них сильно ограниченны. Т.к. каждая выборка из Depth Map стоит времени. В моем варианте мы берем некоторое начальное приближение L и динамически меняем его исходя из расстояния между нашим текселем и позицией, которую мы “восстановили”:
Вспомогательные функции, перевод мировой точки на экранное пространство:
После завершения итераций мы имеет позицию “пересечения с отраженной геометрией”. А наше значение nuv будет проекцией этого пересечения на экран, т.е. nuv.xy – это UV координаты в экранном нашем пространстве, а nuv.z это восстановленная глубина (т.е. abs(GetDepth(nuv.xy)-nuv.z) должен быть очень маленьким).
В конце итераций L будет показывать расстояние отраженного пикселя. Последний этап — собственно добавление отражения к Color Map:
Разбавим теорию иллюстрациями, исходное изображение (содержание Color Map из GBuffer):

После компиляции шейдера (отражения) мы получим следующую картину (Color Map из GBuffer + результат шейдера SSLR):

Не густо. И тут стоит еще раз напомнить, что Space-Screen эффекты это сплошной Information Lost (примеры выделены в красные рамки).
Дело в том, что если вектор отражения выходит за пределы Space-Screen – информация о Color-карте становится недоступной и мы видим Clamping нашего UV.
Чтобы частично исправить эту проблему, можно ввести дополнительный коэффициент, который будет отражать “дальность” отражения. И далее по этому коэффициенту мы будем затенять отражение, проблема частично решается:
Результат, отражение умноженное на error (попытка убрать артефакт SSLR — information lost):

Уже лучше, но мы замечаем еще одну проблему, что будет, если вектор отразится в направлении камеры? Clamping’а UV происходить не будет, однако, несмотря на актуальность UV (x > 0, y > 0, x < 1, y < 1) он будет неверным:

Эту проблему так же можно частично решить, если как-нибудь ограничить углы допустимых отражений. Для этого идеально подходит фишка с углами от эффекта Френеля:
Чуть-чуть модифицируем формулу:
Значения Френеля, с учетом Normal-маппинга (значения fresnel-переменной для SSLR-алгоритма):

Те области, которые отражаются в “камеру” будут черными, и их мы не учитываем (взамен можно сделать fade в кубическую текстуру).
Отражение, умноженное на error и fresnel (попытка удалить большую часть артефактов SSLR):

Кстати, значение Fresnel стоит лимитировать по какому-либо параметру, т.к. из-за “шероховатости” нормалей значение будет на порядок больше единицы (или другого числа-лимитера).
И завершающий этап сегодняшний статьи — это размытие отражений, т.к. идеальное отражение только у зеркала. Степень размытия можно считать как 1-error (чем дальше отраженный пиксель — тем сильнее размыт). Это будет своеобразный вес размытия и хранить его можно в альфа-канале RT-отражений.
Результат (финальное изображение с убранными артефактами и с размытыми отражениями):

Заключение
Так же, стоит добавить некоторую информацию об отражающей способности: насколько четкое отражение, насколько поверхность вообще способна отражать, в те места где SSLR не работает — добавить статическое отражение кубической текстуры.
Конечно, Space-Screen эффекты не являются честными, и разработчики стараются скрыть артефакты, но сейчас в реалтайме подобное (при сложной геометрии) сделать невозможно. А без подобных эффектов игра начинает выглядеть как-то не так. Я описал общую методику SSLR: основные моменты из шейдера я привел. Код, к сожалению, прикрепить не могу, т.к. в проекте слишком много зависимостей.