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

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

Трассировка теней с технологиями AMD: как реализованы тени в The Riftbreaker
Динамически меняющееся время суток, разнообразные погодные эффекты и множество исследуемых биомов делают трассировку лучей в реальном времени отличным выбором для 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 снижает нагрузку на центральный процессор благодаря интенсивному распараллеливанию всех процессов, необходимых для подготовки сцены к трассировке лучей. Распределяя операции между CPU и GPU, удалось найти вычислительную мощность, необходимую для выполнения всех этих операций в каждом кадре. В случае сценария тестирования, включающего в себя около шести тысяч существ, атакующих базу игрока, удалось сократить время рендеринга с 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 году.

 

Источник

game development, raytracing, shadow-mapping, трассировка теней

Читайте также