[Перевод] Трассировка теней с технологиями AMD: как реализованы тени в The Riftbreaker

The Riftbreaker — изометрическая стратегия, сочетающая в себе элементы выживания, исследования и hack«n"slash. Разработанная на собственном движке Exor Studios — Schmetterling Engine 2.0, The Riftbreaker позволяет использовать новейшие разработки в игровой индустрии, одной из которых является трассировка лучей в реальном времени. В этой статье речь пойдет о том, с какими проблемами столкнулись в студии при реализации трассировки лучей в игре и какие нашли для них решения.

image


Динамически меняющееся время суток, разнообразные погодные эффекты и множество исследуемых биомов делают трассировку лучей в реальном времени отличным выбором для The Riftbreaker

Краткий экскурс в трассировку лучей


Мир The Riftbreaker полностью динамичен и разрушаем. Практически все объекты, которые присутствуют в окружении, могут быть подвержены влиянию со стороны игрока. Растительность можно согнуть, сжечь и растворить. Тысячи существ могут роиться вокруг игрока и полностью заполонить экран. Подобный геймплей требует особого подхода к рендерингу полностью динамических теней.

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

image


Фрагмент битвы с боссом. К боссу прикреплен отбрасывающий тень точечный источник освещения, что добавляет сцене большей визуальной точности.

Последние поколения графических процессоров имеют достаточную мощность, чтобы выполнять вычисления трассировки лучей в реальном времени. И появление новых видеокарт позволило студии, наконец, ввести тени с трассировкой лучей, обеспечивающие превосходные результаты по сравнению с традиционными методами теневых карт.

Основной принцип трассировки теней заключается в том, что мы не смотрим на сцену с точки зрения источника света и не ищем всевозможные теневые касты, как это делается в теневых картах. Трассировка лучей позволяет просто запускать лучи в источник света. Если луч попадает в препятствие — значит, прямого освещения от него не будет. Если он достигает источника света, тени не добавляются. Этот алгоритм довольно простой, но при этом дает отличные результаты и предлагает решения типичных проблем отображения теней. Однако он очень требователен к производительности графического процессора.

image


Каждый элемент динамической геометрии сцены может отбрасывать тень. Задача заключалась в том, чтобы эти тени отображались как можно точнее при сохранении производительности.

Добавление совершенно новой технологии рендеринга в собственный игровой движок — задача непростая. В случае с The Riftbreaker здорово помогло сотрудничество студии с AMD. Они предоставили собственную библиотеку GPUOpen RT Shadows, содержащую как решение для трассировки лучей, так и для шумоподавления, которое позволило очистить результаты прохода рэйтрейсинга. Однако, прежде чем начать использовать эту библиотеку, пришлось разработать рендерер DirectX 12 для игрового движка. Причиной тому стал API DirectX Raytracing (он же DXR), представленный в стандарте DirectX 12 Ultimate. Этот API позволяет использовать новые шейдеры и возможности аппаратной трассировки лучей современных графических процессоров.

image


Масштабы присутствия персонажей в The Riftbreaker варьируются от небольших стычек до затяжных сражений с вражескими ордами. Ключевым моментом разработки стало создание правильных оптимизаций для различных ситуаций.

Еще одно преимущество работы с AMD — открытый исходный код их решений. Это позволяет внедрять технологии, совместимые с новейшими игровыми платформами на рынке, в том числе с консолями следующего поколения. Также стоит отметить, что совместимость платформ повлияла на выбор и API рендеринга. Были рассмотрены два варианта: Vulkan и DirectX 12. И хотя Vulkan включает в себя трассировку лучей, этот API недоступен на Xbox или PlayStation, да и, на момент написания этой статьи, на ПК его тоже поддерживает только Nvidia. Переход же на DirectX 12 обеспечивает встроенную поддержку трассировки лучей на Xbox и ПК с Windows, позволяя использовать оборудование любых производителей.

image


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

Преимущества реализации теней с трассировкой лучей могут различаться в зависимости от сценария их реализации. В случае с The Riftbreaker наиболее важными функциями стали:

  • «бесконечное» разрешение теней: качество тени не зависит от расстояния от объекта до камеры, в отличие от традиционных методов теневых карт. Каждый пиксель на экране имеет индивидуально вычисленное затенение, что приводит к более точным и стабильным теням без мерцающих артефактов.
  • изменяющаяся полутень: тени с трассировкой лучей позволяют динамически моделировать такие ситуации, как переход от затянутого тучами неба во время дождя к ярко освещенному полудню.
  • низкая стоимость расчета дополнительных источников света, отбрасывающих тени. В текущей реализации теней с трассировкой лучей в The Riftbreaker можно одновременно рассчитать до 4 отбрасывающих тени источников света без значительного снижения производительности. Стоимость добавления дополнительных источников света в случае теневых карт намного выше.


Все эти преимущества достигаются за счет значительной потери производительности. Даже при использовании новейших графических процессоров, поддерживающих аппаратное ускорение трассировки лучей, значения FPS со всеми включенными эффектами трассировки лучей могут оказаться вдвое ниже при сравнении той же сцены без трассировки.

Реализация теней с трассировкой лучей


Добавление теней с трассировкой лучей к сцене — сложный процесс, результатом которого является крайне подробная карта освещенных и неосвещенных пикселей. Во время первого прохода рэйтрейсинга необходимо восстановить положение всех пикселей в видимой области экрана и направить лучи от этих пикселей ко всем источникам света, которые на них влияют. Эти координаты берутся из буфера глубины. Если луч достигает источника света — значит, поверхность освещена напрямую. Если луч на своем пути встречает препятствие, поверхность окажется затененной. Кроме того, чтобы оптимизировать процесс, все лучи с поверхностей отбрасываются с картами нормалей, обращенными в направлении, противоположном источнику света. На следующем проходе определяется тип шейдера, который будет применяться к пересечению луча и поверхности. DXR API использует в обработке шейдер, основанный на результате трассировки лучей, и сверяет его с существующей таблицей шейдеров.

image


Пример игровой сцены с включенными эффектами трассировки лучей — мягкими тенями и ambient occlusion

Видеокарты серии Radeon RX 6000, использовавшиеся для разработки трассировки лучей в The Riftbreaker, обладают большой мощностью и способны запускать миллионы лучей в секунду. Однако для получения точного представления о том, как свет будет вести себя в игровом мире, потребуется еще больше информации. В случае автономного рендеринга это обычно подразумевает отбрасывание тысяч лучей во всех направлениях на каждый пиксель. Никакое современное оборудование не способно выполнять эти вычисления в реальном времени, не говоря уже о том, чтобы делать это 60 раз в секунду. Значит, нужно каким-то образом создать точную теневую карту, используя неполные данные.

image


Результирующее изображение прохода трассировки лучей перед шумоподавлением. Обратите внимание на нечеткие тени, а также на края острых предметов.

Отсутствие точных данных создает множество проблем и может привести к ухудшению визуального качества сцены. Хотя у нас будет большая часть информации, необходимой для рендеринга объектов, такие детали, как контуры, края и мягкие тени, станут размытыми и смешаются друг с другом. Ограниченное количество лучей на кадр приводит к появлению шумных теней. Тогда в игру вступает другая открытая библиотека GPU — AMD FidelityFX Denoiser. Удаление шума — сложный процесс, который стал возможным благодаря широкому использованию временных методов, анализирующих прошлые кадры и объединяющих их в новый. Шумоподавитель AMD позволяет быстро определять средние значения доступных данных и то, какие свойства нужно применить к заданному пикселю, чтобы получить четкое изображение без каких-либо видимых компромиссов.

image


Та же сцена после удаления шума

image


В шумоподавителе используется модель белого шума, анимированная с помощью золотого сечения. Эта визуализация была описана ​​Аланом Вулфом в его блоге.

Трассировка лучей динамически изменяющейся сцены


Разумеется, реализация теней с трассировкой лучей оказалась не такой простой задачей, чтобы ограничиться использованием пары готовых библиотек. The Riftbreaker представляет свои уникальные задачи, требующие разработки конкретных решений.

Первой подобной проблемой стало огромное количество динамических объектов, присутствующих в игровом мире. В The Riftbreaker вам выпадает роль ученого, исследующего экзопланету, населенную многочисленными инопланетными видами флоры и фауны. На игрока то и дело нападают орды из тысяч инопланетных существ. Каждое из них должно отбрасывать собственную тень. В сочетании с динамической системой растительности, реагирующей на ветер, ударные волны и изгибающие силы, применяемые другими объектами, это стало серьезной проблемой оптимизации.

image


Тысячи сущностей взаимодействуют друг с другом в режиме реального времени

Основная проблема была вызвана тем, как верхняя структура ускорения для трассировки лучей обрабатывает данные. В этой структуре хранится информация об объектах сцены, использующаяся во время прохода трассировки лучей. Храниться эти данные могут только в виде предварительно запеченной структуры ускорения нижнего уровня, которая содержит информацию о вершинах объекта. Это не проблема, если речь идет о камнях или зданиях, однако все юниты со скелетной, динамически смешанной анимацией, а также динамическая растительность совершенно не соответствуют допущению о «предварительно запеченных» данных.

image


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

Чтобы обеспечить структуру ускорения всеми необходимыми данными, пришлось принять некоторые серьезные меры. Каждый динамический объект на сцене индивидуально запекается в совершенно новую статическую модель, которую можно обрабатывать во время прохода трассировки лучей. Чтобы сохранить точность, этот процесс необходимо повторять каждый кадр. Сложности этой задаче добавляет то, что The Riftbreaker имеет динамическую погодную систему. Из-за этого возможна такая ситуация, когда источник света находится под углом, из-за которого объект отбрасывает тень в кадр, не будучи видимым напрямую. Это означает, что в процессе запекания нужно учитывать не только объекты в видимой части экрана, но и за его пределами.

image


Изображение всей структуры ускорения подготовлено всего за один кадр рендеринга

Процесс подготовки структур ускорения является очень громоздким с точки зрения вычислений для ЦП и может легко стать узким местом для всего рендерера. Schmetterling Engine 2.0 снижает нагрузку на центральный процессор благодаря интенсивному распараллеливанию всех процессов, необходимых для подготовки сцены к трассировке лучей. Распределяя операции между ЦП и ГП, удалось найти вычислительную мощность, необходимую для выполнения всех этих операций в каждом кадре. В случае сценария тестирования, включающего в себя порядка шести тысяч существ, атакующих базу игрока, удалось сократить время рендеринга с 60 мс до 17 мс благодаря распараллеливанию задач, зависящих от ЦП (использовался ЦП AMD Ryzen 9 3900X и предрелизная версия Radeon 6800XT).

image


Снимок одного фрейма из The Riftbreaker. Все процессы, необходимые для трассировки лучей, отмечены цветными рамками, легенда представлена в правом нижнем углу. Нажмите на изображение для увеличения

Поддержка альфа-тестирования для трассировки лучей


Еще одна уникальная задача, которую нужно было решить инженерам при внедрении методов трассировки лучей в The Riftbreaker, оказалась связана с системой растительности, хотя и в несколько ином роде. Текстуры, используемые листвой, обычно проходят альфа-тестирование и нередко имеют прозрачные области. Однако для рэйкаста это не имеет значения. Как только луч встречает прозрачный пиксель на текстуре, он возвращает обычное «попадание». Это не обязательно означает, что пиксель, из которого мы производим лучи, должен быть покрыт тенью, ведь если тексель, в который мы попали, будет прозрачным, луч должен продолжать движение к источнику света. В игре таких текстур много, поэтому необходимо было найти решение этой проблемы и добавить поддержку альфа-тестирования в шейдер AnyHit.

image


Альфа-канал широко используется в игре для добавления неровных краев и сложных форм на текстуры растительности. К сожалению, это привело к проблемам с распознаванием попаданий при трассировке лучей.

Подход студии заключался в задействовании решения, используемого в традиционных методах рендеринга. При ударе о поверхность мы получаем барицентрические координаты треугольника в точке пересечения. Этих координат недостаточно, чтобы определить, в какой пиксель текстуры попал луч, и можно узнать только положение точки пересечения в треугольнике. Однако на этом этапе мы можем определить, какие вершины следует учитывать. Каждая вершина треугольника имеет набор UVW-координат, присвоенных ей графическим дизайнером в процессе текстурирования. Зная, в какой треугольник мы попали, координаты пересечения внутри этого треугольника и какая часть текстуры должна его покрывать, мы можем выполнить альфа-тест.

image


Полигоны, лежащие под текстурами растительности, непрозрачны для лучей. Пришлось ввести дополнительный метод проверки, попадают ли они в то место на текстуре, которое действительно было непрозрачным.

Однако прежде, чем все вышеперечисленное произойдет, структуре ускорения необходимо передать информацию о текстурах и их положениях. Для этого и нужна таблица шейдеров, по сути являющаяся банком данных для графического процессора. В ней перечислены текстуры, задействованные в сцене, а также значения, присвоенные им в индексном буфере и буфере вершин. Благодаря таблице шейдеров можно быстро получить все данные о модели и текстуре, необходимые для выполнения последующих шагов затенения.

image


Поскольку действие The Riftbreaker происходит в необитаемом инопланетном мире, здесь можно встретить множество диких животных

Если результат окажется «непрозрачным», применяются данные затенения, и процесс для этого конкретного луча завершается. В случае непрозрачных попаданий проводится альфа-тест. Как уже говорилось, когда луч пересекается с поверхностью, отсюда можно получить барицентрические координаты точки в треугольнике, с которым он столкнулся. Зная эти координаты и обратившись к буферу индексов, можно получить индексы вершин указанного треугольника. Так извлекаются координаты UVW. Имея данные, предоставленные буфером индекса, теперь в буфере вершин можно найти информацию о том, где эти вершины попадают на текстуру. Только после всех этих действий мы получаем ответ на вопрос, столкнулся ли луч с непрозрачной или прозрачной поверхностью. Если альфа-значение в точке пересечения ниже порога прозрачности, луч продолжает пересекать сцену.

image


Так мы получаем точный результат в каждом кадре. Нажмите на изображение для увеличения.

Альфа-тестирование увеличивает стоимость материалов с точки зрения вычислений теней с трассировкой лучей по сравнению с традиционными методами, так что их лучше избегать, где это возможно. В сценарии с джунглями стоимость отправки такого луча примерно на 20% выше, чем у луча, попадающего в непрозрачный объект. Чтобы уменьшить количество попаданий лучей на прозрачные поверхности, необходимы оптимизации посредством ограничения площади поверхности всех прозрачных объектов. Вид камеры в The Riftbreaker изометрический, поэтому количество видимых одновременно многоугольников естественным образом ограничено, и мы можем легко увеличить время просчета полигонов большинства объектов, не влияя на производительность графического процессора.

Заключение


Использование трассировки лучей пошло The Riftbreaker только на тользу. Мир игры стал более правдоподобным, что способствует лучшему в нее погружению. Мелкие детали, добавляемые с помощью трассировки лучей, определенно помогают улучшению восприятия. Увидеть в небе яркую комету, отбрасывающую тень на динамические объекты на земле, — поистине прекрасное зрелище. Пасмурные дни, в свою очередь, встречают игрока мягкими тенями и более приглушенной цветовой палитрой. The Riftbreaker наверняка займет заслуженное место в линейке игр нового поколения.

image


The Riftbreaker появится на ПК и консолях в 2021 году.

© Habrahabr.ru