Декомпозируем игровую графику: технологии под капотом современных игр

Подробно о том, что представляет собой графический стек современных игровых проектов.

Декомпозируем игровую графику: технологии под капотом современных игр

С момента релиза War Robots прошло уже более 7 лет. В 2014 году мобильный игровой рынок был гораздо скромнее, чем сейчас, а девайсов, которые могли без проблем тянуть трехмерную игровую графику, — и того меньше. Несмотря на то, что уже случилась шейдерная «революция», и на замену графического конвейера с фиксированным функционалом (fixed-function pipeline) пришли вершинные и фрагментные шейдеры, возможностей для создания качественной картинки уровня настольного компьютера было явно недостаточно.

В основе же работы с любой графической системой лежит набор стандартизированных методов, маскирующих обращения к видеодрайверу для передачи команд графическому процессору — или, иными словами, контракт, в котором прописано, как с ней обращаться. Его называют графическим прикладным интерфейсом программирования — API (application programming interface). На старте разработки оригинальной игры фактически единственным среди графических API на мобильных платформах (Android, iOS) был OpenGL ES 2.0. Результат его эволюционного развития, OpenGL ES 3.0, был только-только утвержден, и на рынке даже не было устройств, которые бы его поддерживали. Таким образом, графика в Walking War Robots была основана на технологиях и возможностях, предоставляемых именно OpenGL ES 2.0.

У War Robots тех времен был вполне себе типичный графический стек, поддерживающий один направленный источник света и способный рассчитать от него затенение с учетом весьма простой системы материалов. Но в то же время игру отличали и довольно смелые решения: например, уже тогда применялась технология отрисовки террейна со сплатмапой, за счет плавного смешивания позволяющая рисовать протяженные комплексные поверхности без повторений однотипных мелких рисунков. Хотя и не все набирающие популярность методы нашли место в проекте — скажем, запеченное освещение (лайтмапы и лайтпробы) и система с множественными материалами тогда его обошли стороной.

Со временем графика в игре улучшалась и совершенствовалась, но довольно быстро ее развитие стало упираться ограничения OpenGL ES 2.0. Например, для полноценного использования получающих все большее распространение PBR-техник (physically-based rendering — PBR) нужна была возможность работы в линейном цветовом пространстве, что являлось неразрешимой проблемой для GLES 2.0. Наступил момент, когда потенциал эволюционного развития был достигнут, и без комплексного революционного подхода рывок в графике уже не представлялся возможным.

Декомпозируем игровую графику: технологии под капотом современных игр

Первая итерация remastered-версии — прототип для Steam

К сожалению, несмотря на бытующее в некоторых кругах мнение, невозможно улучшить качество картинки в игре, просто «выкрутив настройки на максимум». А улучшить качество картинки в игре, которая находится в оперировании много лет, постоянно меняясь и развиваясь, — задача крайне нетривиальная. Как минимум, не выйдет сделать графику с нуля, без оглядки на ожидания игроков и на то, что уже прижилось в игре. Нужно очень бережно обращаться с существующим геймплеем и атмосферой, учесть огромное количество деталей, причем зачастую неочевидных. И, конечно, где долгая история активного оперирования, там легаси. За годы существования War Robots, в игре накопилось множество крайне неочевидных решений: от уникальных и нужных, удивляющих своей изящностью, до поражающих воображение художественных костылей, когда-то решавших разнообразные технические проблемы, которые неизбежно приходили в проект с каждой новой версией Unity.

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

К счастью, была возможность проверить идеи и уточнить многие детали с минимальным привлечением основной команды разработки: провести эксперимент на версии War Robots для Steam. Она хорошо подходила для этой цели по многим параметрам: практически полностью совпадающая кодовая база и арт, сравнительно небольшое количество игроков, при этом в среднем изрядно более мощное железо у этих самых игроков позволяло не так сильно заботиться об оптимизации на данном этапе, а сосредоточиться на красочной и насыщенной картинке.

В общих чертах идея эксперимента выглядела так:

  • определяемся с тем, как глубоко и какими средствами мы улучшаем картинку;
  • в рамках одной игровой карты перерабатываем графику (рендерер, модели, текстуры, шейдеры, свет, тени, обработку, эффекты, анимацию и т.д.) так, чтобы картинка ожила;
  • в процессе определяем объемы возможных работ по полной модернизации графики;
  • по результатам экспериментального релиза на Steam решаем, необходима ли такая модернизация вообще.

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

В качестве перерабатываемой карты была выбрана Canyon: на ней не так много геометрии, к новому игроку она попадает не первой, а потенциал к улучшению имеет значительный.

Декомпозируем игровую графику: технологии под капотом современных игр

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

Чтобы получить первые быстрые результаты по сцене, часть геометрии окружения была заменена готовыми ассетами, а текстуры одного из роботов доработаны из исходников до технически корректного PBR. Немного доработок по свету, небольшая доработка пары шейдеров — и сцена начинает выглядеть чуточку современнее:

Декомпозируем игровую графику: технологии под капотом современных игр

На получившейся картинке, помимо всего прочего, явно заметна нехватка динамического диапазона: освещение слишком однородное, будто в пасмурный день или в старой игре. В реальности освещенность ярких участков такой сцены может превосходить освещенность участков в тени в тысячи и десятки тысяч раз и доходить до сотни тысяч люкс. Невозможность работать с таким диапазоном (и значениями выше 1.0) при использовании буферов отрисовки форматов вроде R8G8B8A8_UNorm (8 бит беззнаковый целочисленный на канал) приводит к следующему почти обязательному требованию PBR — возможности отрисовки в широком динамическом диапазоне. Для этого используются буферы с плавающей запятой разной точности: от R32G32B32A32_FLOAT до формата R11G11B10_FLOAT. Табличка для понимания:

Декомпозируем игровую графику: технологии под капотом современных игр

Из таблицы видно, что, например, формат R32G32B32A32_FLOAT имеет точность 7.22 ненулевых знаков и огромное максимальное значение, однако требует значительно большего объема памяти для хранения — в 4 раза больше, чем R8G8B8A8_UNorm. На практике для хранения значений кадра в широком динамическом диапазоне нам достаточно максимального значения и точности R16G16B16A16_FLOAT — он и использовался в версии для Steam. Более того, в большинстве случаев и при должном обращении достаточно и точности, обеспечиваемой форматом R11G11B10_FLOAT. Этот формат занимает в два раза меньше памяти, чем R16G16B16A16_FLOAT, и в точности вписывается в тот же «битовый бюджет», что и R8G8B8A8_UNorm. Отсутствие четвертого канала и вероятность возникновения небольшого цветового сдвига по причине меньшей точности синего канала не играют значительной роли, поэтому в мобильной версии мы по возможности используем его.

После получения кадра и постобработки получившегося HDR-изображения диапазон необходимо вернуть в рамки значений, доступных для вывода на экран, — для этого применяется процедура тонального отображения (tonemapping). Как в ремастере версии для Steam, так и в ремастере мобильном почти всегда мы используем алгоритм тонального отображения ACES: он позволяет получить «кинематографичную» картинку со слегка выжженными цветами в ярких областях.

На самой сцене больше всего изменений претерпел ландшафт. Логично было никак не затрагивать геймплей сцены — а значит, форма ландшафта в игровой зоне должна была остаться абсолютно такой же. Для этого с игровой зоны была снята карта высот (с точностью ±4 см), а на ее основе был процедурно сгенерирован новый ландшафт, изменения в форме которого касались только заднего плана. Текстуры ландшафта были, конечно же, перерисованы, маски сгенерированы, тесселяция добавлена, ручей налит, а после — подсушен. На небе появились динамические облака, в воздухе — пыль и дымка, а мост в центре карты — в очередной (но не в последний) раз переделан. Для понимания дальнейшего направления этого было достаточно.

Декомпозируем игровую графику: технологии под капотом современных игр

Помимо сцены, улучшения получили и роботы. Под переработку попало более десятка роботов из числа популярных. Первым делом, если не нужны были существенные правки геометрии, от аниматора роботы получали новенький индивидуальный скелет на generic риге вместо общего на всех скелета на Humanoid, а также индивидуальный набор анимаций. Текстуры были либо доведены до адекватного PBR и доработаны в случае, если исходники текстур рисовались в Painter, либо перерисованы на базе имеющихся с нуля, либо использовали оригинальные маски (при наличии таковых).

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

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

Также были переработаны почти два десятка единиц вооружения: текстуры заменены на PBR, изменены некоторые анимации, слегка доработаны шейдеры эффектов, а для выстрелов и взрывов добавлены источники света.

Декомпозируем игровую графику: технологии под капотом современных игр

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

Для каждой сцены на основе старых текстур был сгенерирован новый набор: выше разрешением и включающий в себя все необходимые карты для корректной работы PBR-шейдера. Некоторые из новых текстур были доработаны вручную для более корректной передачи физических свойств материалов, так что итоговый результат получился вполне адекватным, учитывая его полуавтоматическую природу. Также на каждой карте был настроен свет, постобработка и прочие параметры сцены и объектов окружения, связанные с освещением. На некоторых картах были доработаны модели, расставлены дополнительные источники освещения, а небо было заменено на динамическое. С помощью подключившихся на завершающем этапе художников на некоторых сценах был переделан ландшафт и, наконец, на всех картах были сделаны настройки для глобального освещения в реальном времени и запечен свет. Результат, конечно, не поражал, но разница с Canyon хотя бы не так бросалась в глаза.

Было/стало:

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

Релиз экспериментальной версии для Steam случился в конце 2018 года. По его итогам были сделаны следующие выводы:

  • Не стоит недооценивать негативную реакцию пользователей на повысившиеся требования к железу;
  • Нужно аккуратно подходить к изменению привычных анимаций роботов: люди способны неплохо определять неврологические заболевания по походке. Особенно у Гриффина.
Декомпозируем игровую графику: технологии под капотом современных игр
  • Motion blur в нашем жанре не нужен;
  • Физически корректное освещение — это хорошо, но к освещению сцен стоит подходить с учетом влияния контраста на геймплей;
  • Яркие вспышки от взрывов и выстрелов мешают стрелять и взрывать;
  • Ремастер для мобильных платформ — нужен.

Следующий этап — перенос ремастера на мобильные устройства

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

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

Как реализовать графику десктопного уровня на мобильных устройствах и в то же время не снизить производительность графики в целом?

Компромисс нашелся в решении разделить устройства по уровню производительности и подготовить несколько пресетов качества. Каждый пресет отличается набором контента (количество и разрешение текстур, полигонаж объектов, наполнение игровых уровней) и стеком используемых графических решений (модель освещения, детализация отрисовки объектов, сложность эффектов постобработки). Таким образом, весь ассортимент мобильных устройств разделился на три категории — HD (high definition), LD (low definition) и ULD (ultra-low definition).

Так выглядит игра в ULD-пресете
Так выглядит игра в ULD-пресете
Так — при LD-настройках
Так — при LD-настройках
Так — в HD
Так — в HD

Современные топовые мобильные устройства без труда могут потянуть высоконагруженный графический стек — они и сформировали группу для HD-пресета качества. Самый массовый сегмент, включающий в себя устройства среднего уровня производительности, получил LD-пресет. А для совместимости с устройствами, которые из последних сил «вытягивали» оригинальную игру, сделан облегченный ULD-пресет. Таким образом, сформировались три группы девайсов, в каждой было выбрано свое референсное устройство (девайс или графический процессор), под которое готовился контент и настраивался графический стек.

Целевые устройства для разных пресетов качества
Целевые устройства для разных пресетов качества

Но даже в пределах каждой из трех групп разброс производительности оказался в достаточно широких пределах и требовал более точной подстройки для комфортной игры. Поэтому для сглаживания изменений частоты кадров мы стали применять адаптивную подстройку разрешения отрисовки сцены. Изменение разрешения практически напрямую влияет на объем нагрузки на графический процессор и может варьироваться в реальном времени в зависимости от происходящего в игре, основываясь на истории нескольких последних кадров. Полноэкранное сглаживание (MSAA) эффективно маскирует моменты смены разрешения, снижая «ступенчатость» и «замыленность» картинки.

Декомпозируем игровую графику: технологии под капотом современных игр

Таким образом, в ремастере имеет место «двухэтапная» схема масштабирования производительности:

  • на первом этапе для грубой настройки выбирается контент и графический стек разной степени сложности — один из трех пресетов качества;
  • на втором этапе для тонкой настройки подстраивается разрешение отрисовки, обеспечивая плавный и комфортный игровой процесс.

OpenGL ES vs. Metal & Vulkan — что выбрать?

Для работы с обновленным контентом от графического конвейера требовалась поддержка таких функций, как многопроходная отрисовка (multi-pass rendering), выборка из текстурных массивов (texture arrays), запись в буферы цвета вещественного формата (float-point color buffers). Используемый изначально в проекте OpenGL ES 2.0 все это поддерживать не мог. Отсюда — возникла необходимость перехода на более современный графический API, тем самым заодно повысив удобство работы и улучшив производительность.

На iOS очевидным выбором стал Metal API, который поддерживался на 99,2% устройств и полностью соответствовал нашим требованиям. Кроме того, замена OpenGL ES на Metal API рекомендуется самой компанией Apple. Он обладает гораздо более гибким функционалом и высокой производительностью, а также удобными средствами отладки и профилирования.

Android предлагает выбор между двумя графическими API: OpenGL ES 3.0+ и Vulkan. Первый существенно превосходит свою предыдущую редакцию 2.0 по функционалу, имеет прекрасно отлаженные драйверы и работает на 97,1% устройств пользователей, но при этом концептуально морально устарел и имеет весьма туманные перспективы. Альтернативой OpenGL ES является Vulkan — низкоуровневый графический API, идеологически близкий к Metal.

Результаты экспериментов с Vulkan на мобильных устройствах подтвердили более «ровную» производительность графического конвейера ремастера по сравнению с OpenGL ES. Вместе с этим доступность Vulkan API и его стабильное функционирование подтверждено лишь на 63% устройств, что делает его использование слишком рискованным. Так, например, в Unity в Scriptable Render Pipeline совсем недавно была добавлена модель RenderPass/SubPass, которая в полной мере позволяет раскрыть потенциал Vulkan API на мобильных платформах. К сожалению, на момент выпуска ремастера модель осталась незадействованной, вследствие чего результаты производительности при использовании Vulkan API по сравнению с OpenGL ES 3.0 оказались неоднозначными и отличались от устройства к устройству.

В результате в качестве графического API на Android мы остановились на OpenGL ES 3.0, а поддержка Vulkan пока остается в статусе экспериментальной.

Тени, освещение, постобработка — из каких этапов состоит отрисовка графики

«Двухэтапная» схема масштабирования производительности и переход на современные графические API позволили заложить основу для разработки гибкого и производительного графического конвейера. В результате для всех пресетов качеств — ULD, LD, HD — используется унифицированный многопроходный конвейер отрисовки, отличающийся набором входных данных и вариантами их обработки. Так, различаются разрешения текстур и детализация геометрии, сложность шейдеров и конфигурация проходов отрисовки.

Различия наборов текстур в пресетах
Различия наборов текстур в пресетах

Технологически отрисовка каждого кадра состоит из трех основных этапов: проход отрисовки теней, проход наложения освещения и проход постобработки.

Различия проходов отрисовки в пресетах
Различия проходов отрисовки в пресетах

Проход отрисовки теней использует две карты теней (shadow map). Первая из них представляет собой один каскад и обновляется каждый кадр, включая в себя объекты в области видимости камеры на близких расстояниях. Для объектов вдалеке от камеры используется глобальная предрассчитанная карта теней (shadow masks) с меньшей точностью границ тени (umbra) и полутени (penumbra). При расчете освещения выборки из обеих карт теней смешиваются друг с другом для незаметного и плавного перехода между ними и используются для затенения. Таким образом, в каждом кадре обрабатывается только небольшое подмножество объектов вблизи камеры, что позволяет существенно снизить нагрузку по обработке геометрии. В то же время использование прерассчитанной карты теней позволяет отображать тени от объектов по всей площади сцены.

При отрисовке геометрии в карту теней порядок следования индексов треугольников изменяется на обратный для более эффективного отсечения — это называется front-face culling. В результате этого значительно снижается нагрузка на растеризатор, ведь порядка 90% треугольников отбрасывается еще на раннем этапе. Карта теней при этом получается достаточно разреженной, что дополнительно повышает производительность при выборке и сравнении значений из нее. На картинках ниже для сравнения — карты теней с результатом классической обрисовки и инверсной.

Карты теней с обратным (слева) и прямым (справа) отсечением треугольников

Проход наложения освещения рассчитывает интенсивности освещенности объектов в сцене от одного основного источника света. Его вклад традиционно формируется из двух составляющих:

  • прямое освещение (direct), рассчитываемое в реальном времени;
  • непрямое освещение (indirect), выбираемое либо из предрассчитанных карт освещенности (lightmaps) для статических объектов, либо из ближайших зондов освещенности (lightprobes) для динамических объектов.

Сцена без света, только с прямым освещением, Indirect diffuse, Indirect specular, Indirect diffuse + indirect specular и, наконец, все вместе:

И для того, и для другого используется отрисовка в широком динамическом диапазоне (high dynamic range) c пофрагментным вычислением двухлучевой функции отражательной способности (bidirectional reflectance distribution function).

При расчете освещения на всех объектах в сцене используется одинаковая физически достоверная (physically based) модель. Благодаря этому мы можем применять для хранения параметров материала общие на все объекты в сцене текстурные массивы. Среди параметров материалов — альбедо (albedo), гладкость (smoothness), металличность (metallnes), нормали (normal) и значение окружающего затенения (ambient occlusion). В результате мы используем всего пять основных шейдеров для отрисовки всех объектов в сцене: mechs/drones/equip shader, terrain shader, decal shader, unique props shader, detail props shader.

Некоторые шейдеры вместо привычной карты нормалей в касательном пространстве используют карту частных производных высоты, а шейдер ландшафта использует карту высоты вместо карты металличности
Некоторые шейдеры вместо привычной карты нормалей в касательном пространстве используют карту частных производных высоты, а шейдер ландшафта использует карту высоты вместо карты металличности

В проходе постобработки производится сжатие широкого динамического диапазона в диапазон, подходящий для вывода на экран с помощью тонального отображения, а также цветокоррекция (color grading), виньетирование (vignette) и, при необходимости, конверсия цветового пространства (gamma space conversion). Поверх получившегося изображения рисуются элементы графического интерфейса (UI) и после этого, наконец, следует вывод на экран.

Сцена без постобработки, c тональным отображением, тональным отображением и цветокоррекцией, финальная: с тональным отображением, цветокоррекцией и виньетирование:

Не только улучшенная картинка, но и производительность: снижаем время отрисовки кадра и разгружаем ЦП

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

Большое разнообразие материалов в сцене обычно сопровождается частой сменой ресурсов между вызовами отрисовки. Поскольку в процессе перепривязки ресурсов (resource binding) графический процессор не может заниматься отрисовкой, это приводит к вынужденным ожиданиям, а значит — к неполной загрузке ЦП. Для борьбы с этим происходит группировка вызовов отрисовки с одинаковыми материалами для последовательного исполнения (batching). Однако, если каждый материал в сцене уникален, традиционный подход группирования будет неэффективным и потребует перепривязки ресурсов практически при каждом вызове. Поэтому обычно количество уникальных материалов в сцене фиксировано, что накладывает ограничения на свободу действий при дизайне игровых уровней и подготовке контента.

Графический пайплайн ремастера не накладывает ограничения на количество уникальных материалов в сцене, поскольку не требует перепривязки ресурсов. Так, все текстуры из уникальных материалов собраны в текстурные массивы (texture array), а дополнительные параметры скомбинированы в единый константный буфер (uniform buffer).

Схема комбинирования материалов (констант и текстур)
Схема комбинирования материалов (констант и текстур)

Привязка таких «собранных» ресурсов происходит единожды вместе с соответствующим шейдером и не меняется на протяжении всех вызовов отрисовки, использующих этот шейдер. Нужный материал выбирается из коллекции непосредственно в шейдере за счет обращения к соответствующему слою текстурного массива по индексу и через рассчитываемый отступ до соответствующего элемента в константном буфере. Таким образом, число перепривязок ресурсов строго равно числу уникальных шейдеров, используемых в сцене. В ремастере в каждой сцене используется в среднем 12 вариантов шейдеров, получаемых из пяти основных за счет использования ключевых слов (keywords).

В результате на 300-400 вызовов отрисовки в кадре приходится в среднем по 20 перепривязок ресурсов, благодаря чему время подготовки кадра практически не зависит от числа уникальных материалов.

Техническая реализация такого решения требует поддержки со стороны графического API двух возможностей: выборки из текстурных массивов (texture array fetching) и использования динамических константных буферов (dynamic uniform buffer). Графический конвейер ремастера полностью поддерживает SRP batching на Metal и Vulkan и частично на OpenGL ES 3.0. Тут стоит напомнить, что использование текстурных массивов предполагает одинаковый формат, разрешение и количество mip-уровней в слоях. Динамические константные буферы, в свою очередь, требуют строгого соблюдения специфичного для каждого устройства шага выравнивания при установке отступов. Для большинства графических процессоров Mali это 16 байт, а для графических процессоров Adreno — 64 байта.

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

  • для минимизации перерисовки пикселей (pixel overdraw) геометрия предварительно распределяется по небольшим участкам в экранном пространстве — тайлам;
  • каждый тайл обрабатывается независимо, локализуя отрисовку небольшой областью экрана;
  • при обработке тайла его геометрия сначала сортируется, а потом уже отрисовывается, что позволяет достичь того же эффекта, как и при предварительной отрисовке в буфер глубины (z-prepass) на стационарных платформах.

Отметим, что использование особенностей тайловой архитектуры не требует каких-либо действий или установок со стороны графического API и неявно выполняется видеодрайвером.

Другим важным преимуществом тайловых архитектур является наличие тайловой памяти. Она расположена непосредственно на GPU и позволяет избегать довольно энергозатратного экспорта/импорта промежуточных данных в видеопамять. Типичными сценариями использования тайловой памяти являются разрешение сэмплов полноэкранного сглаживания (multi-sample anti-aliasing resolving) без дополнительного прохода, создание «виртуальных» буферов без выделения памяти (memoryless attachments), использование временных буферов (transient attachments) между проходами отрисовки. Для работы с тайловой памятью на современных API (Metal/Vulkan) предусмотрены явные методы, в то время как OpenGL ES 3.0 позволяет только задать определенные подсказки видеодрайверу. В ремастере для всех поддерживаемых графических API применяется полноэкранное сглаживание (MSAA) без отдельного прохода разрешения (resolve) и без использования промежуточной видеопамяти (memoryless) под семплы.

Отладка и диагностика: как отследить, что с новыми технологиями все в порядке

Любой проект с высокой нагрузкой будет требовать постоянного контроля производительности. Профилирование графики правильнее всего планировать на самом начальном этапе, как только более или менее сформирован графический стек. Так, при работе над ремастером мы обновили автоматические бенчмарки, измеряющие производительность при отрисовке сцен, мехов/экипировки и эффектов. Так мы смогли оперативно выявлять и реагировать на регрессии, а при необходимости — глубже изучали причины просадок. Для этого у нас в ходу такие инструменты, как Qualcomm Snapdragon Profiler, ARM Graphics Analyzer и Xcode Frame Debugger — именно с их помощью происходит диагностика проблем, специфичных для отдельных графических процессоров, и довольно заметно влияющих на производительность:

  • «проливание» регистров графического процессора (GPU register spilling), характерное для сложных вычислений;
  • излишний импорт/экспорт данных из тайловой памяти в глобальную при работе с полноэкранным сглаживанием и составляющими буфера кадра (framebuffer attachments);
  • наличие в сцене недружественной для тайловых архитектур геометрии, состоящей из длинных вытянутых треугольников;
  • чрезмерное использование прозрачных и полупрозрачных материалов, существенно увеличивающее перерисовку пикселей (pixel overdraw);
  • оптимальное соотношение между арифметическими операциями и операциями чтения/записи, приводящее к неполной загрузке графического процессора;
  • эффективность использования кэша 1-го и 2-го уровня для предвыборки из текстур и снижения задержек доступа к данным.

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

Пример окна ARM Graphics Analyzer
Пример окна ARM Graphics Analyzer
Пример окна Qualcomm Snapdragon Profiler
Пример окна Qualcomm Snapdragon Profiler

Помимо мониторинга эффективной работы «железа» конкретных мобильных систем, при работе с Unity не менее важно уделять внимание корректности вызовов графических API. Для проверки GLES 3.0 и Vulkan мы использовали RenderDoc, а для Metal — Xcode Frame Debugger. С их помощью можно детально проверить:

  • структуру кадра отрисовки (установка шейдеров и привязка ресурсов);
  • промежуточные состояния графического конвейера (настройка теста глубины, параметров альфа-смешивания, переключения буферов кадра);
  • консистентность ресурсов (формат, разрешение, компрессия).

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

Декомпозируем игровую графику: технологии под капотом современных игр
Декомпозируем игровую графику: технологии под капотом современных игр

Подводя итоги: об опыте работы над новым графическим пайплайном

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

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

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

Павел Кирсанов
Lead Graphics Developer
Роман Вишняков
Lead Technical Artist
123123
26 комментариев

Нормальная статья о геймдеве на дтф *о*

22
Ответить

И это середина цикла статей, у нас еще есть :)

9
Ответить

играю щас в метро Историю сема(первую, не РТХ версию). мне кажется, или разрабы зафакапили рендер в этом аддоне?  Ну не может же быть так всрато, словно вообще без затенения

5
Ответить

Хм. По скриншоту кажется, что вроде бы все нормально?

Ответить

У меня абсолютно такое же ощущение осталось. В основной сюжетке все красиво, а в Истории Сэма графоний не дотянули.

Ответить

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

Ответить

Отличная статья, спасибо!

2
Ответить