Screen space reflections что это
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 вроде все понятно, это обычные 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
Screen space reflections что это
Информация взята с сайта http://gamegpu.com/
Потребление ОЗУ игрой с различными настройками графики:
Потребление RAM всей системой во время игры с максимальными настройками графики (зависит также от количества запущенных фоновых программ):
Q: у меня gtx 780ti или gtx970\980 и игра тормозит на максимуме! Что за отвратительная оптимизация, раз игра тормозит на топовых видеокартах?!
A: без паники! Во-первых, текстуры максимального разрешения рассчитаны на видеокарты с памятью более 6-ти ГБ. Поэтому выберите «высокое» качество текстур. Во-вторых, обратите внимание на сглаживание, поставьте SMAA или FXAA. Скорее всего после этого лаги пропадут.
Q: у меня 2 ГБ видеопамяти и игра очень сильно тормозит. Что делать?
A: если у вас видеокарта оснащена только 2-мя ГБ памяти (например, некоторые версии gtx960), то поставьте качество текстур на «средние» и попробуйте перезапустить игру.
Q: у меня игра сильно тормозит на максимуме! Какие опции в первую очередь необходимо снизить?
A: 1) Поставьте сглаживание SMAA или FXAA. 2) Динамическую листву поставьте на средние. 3) Детализацию на «высоко» или ниже. 4) PureHair просто «ВКЛ». 5) Качество теней на «средние». 5) Если у вас видеокарта серии GTX7XX или ниже, выключите тессиляцию. 6) Качество отражений поставьте на минимум.
Q: какие опции могут испортить графику?
A: 1) «Глубина резкости» размывает изображение, некоторым может не понравится. 2) «Зернистость плёнки» добавляет шумы и артефакты на изображение. 3) «Размытие по краям» также не всем игрокам придётся по вкусу. 4) «Мягкие тени от солнца» слишком сильно размывают тени, особенно когда опция «качество теней» выбрана ниже чем «очень высоко».
Q: у меня очень слабый компьютер. Я играю на полном минимуме, но у меня есть запас мощности. Какие опции включить в первую очередь, чтобы существенно улучшить графику?
A: 1) Обязательно включите «Преграждение окружающего» 2) «Динамическую листву» поставьте на «средние». 3) «Детализацию» на «средние». 4) Включите «Отражения пространства экрана», но в последнюю очередь 5) «Качество теней» очень сильно влияют на качество графики, поэтому постарайтесь поставить тени хотя бы на «минимум», это очень важно. 6) На «качество текстур» влияет только объём видеопамяти, поэтому поставьте на «средние» или «высокие».
Q: у меня в игре fps нормальный, но в кат-сценых игра тормозит! Что делать?
A: «Pure Hair» и «глубина резкости» в длинных роликах автоматически переключаются на максимум вне зависимости от выбранных настроек, поэтому выключите соответствующие опции.
Q: у меня всего лишь 2 ГБ ОЗУ. Я не смогу поиграть в эту игру?
A: сможете! Увеличьте файл подкачки. Загрузки в игре и быстрые переходы на другие зоны у вас будут занимать 8-15 минут. Также во время перехода из одной зоны в другую игра будет подвисать на 30-40 секунд в течение нескольких минут.
Q: у меня очень старый ПК. Ну там gt440+Core 2 Duo E4400. Мне остаётся только смотреть прохождение игры на youtube?
A: нет! В это сложно поверить, но я прошёл игру именно на gt440+ Core 2 Duo E4400 (2.65 GHZ). В игре было 17-25 fps на 1280х720.
Обман игроков, или как устроены отражения в играх.
ПРЕДИСЛОВИЕ
Довольно часто разработчики игр пытаются сделать отражения в своих играх как можно более правдоподобными, но знаете ли вы, что с отражениями в реальной жизни они не имеют ничего общего. Практически всегда это обман. Создать эффект отблеска зеркал, переотражения на воде, преломление света от осколков стекла помогают многочисленные ухищрения и упрощения создателей игр. Сегодня нескольких таких методах мы и поговорим.
МЕТОДЫ
1. Рендер сцены с нескольких ракурсов. (planar reflections)
Это пожалуй самый распространённый метод создания зеркальных поверхностей в играх. Сцена (видимая игроком часть локации) рендерится (рендер — отрисовка кадра, либо сцены) с нескольких точек, далее уже накладывается на слой, которому нужно создать эффект отражения. Этот процесс добавляет много «гемороя», так как рендер сцены «съедает» очень много ресурсов компьютера, соответственно разработчикам игр требуется дополнительное время на оптимизацию. Довольно часто о таком методе вспоминают только под конец создания проекта, поскольку приоритет стоит у более важных аспектах игры (Например проработка персонажей, создание ландшафта и проработка мира). Пример на скриншотах внизу.
2.Полностью созданная зеркальная комната.
Это был очень популярный способ до начала 2000-х годов. Использовался метод в 99% случаев только для создания зеркал. Он ещё более ресурсозатратен, чем первый способ, зато очень простой в создании. Для начала создаются две абсолютно одинаковых комнаты, выставляется всё те же объекты, те же источники света, вообщем обе комнаты просто дублируются. Самое главное то, что вместо зеркала было просто отверстие в другую комнату, а другая комната просто отражалась по горизонтали. Естественно и сам персонаж в комнате-зеркале spawnился(создавался) и отрисовывался заново. По причинам всё большего нарастания количества объектов в локациях данный метод на сегодняшний день мало кем используется. Пример на скриншотах внизу.
3. Screen-space reflections (упрощённая трассировка лучей).
SSR (Screen-space reflections) появилась задолго технологии RTX от Nvidia, но в целом использует похожий принцип. Однако, в отличие от технологии Nvidia, такой метод задействует трассировку только для тех объектов, которые находятся в поле зрения игрока, остальные же объекты не просчитиваются для экономии ресурсов ПК. Это логично, так как технология впервые появилась в 2011 году, и представила её компания Crytek в своей Crysis 2, а после и в Crysis 3, в то время мощность видеокарты просто не позволяла разработчикам рендерить лишнее. Сейчас же такая технология присутствует во всех современных «движках» («движок» — ПО для создания игры) таких как Unreal Engine 4, Unity, CryEngine и других. Пример на скриншотах внизу.
4. Qube maps (кубическая карта).
Способ очень популярный, хотя не без своих изъянов, таких например как отсутствие игрока в отражении, поскольку кубическая карта «prerender» объект («prerender» объект — объект, отрисованый до присутствия персонажа в локации) а также большая степень размытия, из за чего qube maps нельзя использовать для зеркал. Кубическая карта состоит из шести граней куба, у которого на каждую грань «накладывается» своя текстура. Каждую текстуру можно увидеть только по отдельности, смотря в одно из шести направлений. Определяется такая текстура в зависимости от того, куда смотрит центральная точка на экране игрока. Метод используется как в настоящее время, так и в недалёком прошлом, так как не требует большого количества ресурсов ПК. Саму технологию представила Nvidia в 1999 году вместе со своей видеокартой GeForce 256. Примеры на скриншотах.
5. RTX (Ray Tracing). Трассировка лучей от Nvidia.
Многие считают, что RTX просчитывает тени, источники света и отражения также, как и в реальной жизни, но это не так. Ray Tracing это тоже лишь имитация, но основанная на природных и физических явлениях. Вообще в целом RTX — это целый набор различных технологий, таких например как: создание динамических теней; реалистичных отражений; реалистичных источников света, а также степень их преломления от объектов (перечислена лишь малая часть, на деле их гораздо больше). Благодаря тому, что в видеокартах серии RTX имеются RT ядра и достигается высокая производительность и приемлемый FPS, так как нагрузка на просчёт отражений ложится на них, а не на видеоядро. На самом деле, такой метод может работать и на видеокартах линейки GTX (пример: GTX 1080, 1070), но производительность будет очень низкой. Немного о том, как работает сама технология: это метод комбинированной отрисовки кадра, где отлеживается траектория лучей света во всех точках пространства. Он даёт возможность определить степень освещённости, степень отражения и преломления объектов. Даже сейчас, в 2020 году использовать «на полную» RTX не получается, так как мощности нынешних видеокарт всё ещё не хватает, но будем надеяться на лучшее. Примеры RTX на скриншотах внизу.
6. iRAY. Трассировка лучей на GTX видеокартах.
iRAY на самом деле редко используется непосредственно в играх, зато очень часто использовалась (пока на замену не пришёл RTX) в создании 3D моделей для этих самых игр. О том как работает «Nvidia iRAY» достаточно мало информации, но принцип схож с трассировкой лучей на видеокартах 2000 серии, хотя и с большим количеством упрощений и послаблений (так как до недавнего времени работала только на GTX видеокартах, поддержку RTX добавили в прошлом году). Примеры на скриншотах ниже (с помощью него созданы источники света, отражения на полу на первом скриншоте и в окнах на втором скриншоте).
7.Global illumination и shadow map (глобальное освещение и карты теней).
8. Дополнительная камера.
Этот способ довольно редко используется в играх, так как требует очень много ресурсов и в целом он очень похож на способ #1, однако он очень прост в реализации, поэтому его используют в основном неопытные разработчики. Суть в том, что помимо камеры игрока (через неё вы видите всё, что происходит на экране) создаётся ещё одна с таким ракурсом, чтобы кадр для последующего отражения получился естественным. Далее на полученный кадр накладываются эффекты (самый частый из них это размытие) и для экономии ресурсов понижается разрешение (но даже с пониженным разрешением ресурсов требуется слишком много). Кроме высокого потребления ресурсов ПК, ещё одним недостатком является статичность кадра, то есть где бы ваш персонаж не встал, отражение не перестроится (хотя через «множество костылей» это можно реализовать, но это очень глупо, поскольку есть способы лучше, тот же SSR). Примеры на скриншотах внизу.
КОНЦОВКА
Сегодня вы узнали для себя чуть больше об отражениях в играх, надеюсь вы не жалеете о потраченном времени на прочтение, я же в свою очередь за уделённое мне время вас благодарю. (Можете также посмотреть новый блог о самых популярных игровых условностях у меня в профиле, мне будет приятно если именно вы его прочитаете)
ССЫЛКИ НА ВСЕ ИСТОЧНИКИ
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 вроде все понятно, это обычные 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