Как оптимизируют графику в играх — поиск проблемы, приёмы и портирование

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

Embedded Image

Всё удовольствие даже от самой хорошо написанной игры с продуманными механиками может испортить мыльная картинка или постоянные тормоза. И дело даже не в том, что графика важнее геймплея — если игра сделана спустя рукава, некоторые пользователи просто не смогут её запустить.

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

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

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

Профилировщик в Unity

Разработчики Tom Clancy’s Rainbow Six: Siege не хотели каждый раз воспроизводить проблемную ситуацию для оптимизации или исправления бага, поэтому заложили в свой профилировщик систему тэгов, благодаря которой могли проследить загрузку конкретного ассета. Когда система улавливала проблему с FPS или кадр со слишком долгой отрисовкой, она автоматически делала «снимок» этого момента — подробно расписывала все функции, которые работали в это мгновение, и указывала процессор, на который они повлияли. Кроме того, утилита хранила отдельные логи производительности каждого из игроков. Это экономило время при исправлении ошибок.

Последовательные вкладки профилировщика Rainbow Six: Siege Игрок → Игровые системы (в данном случае проблема вызвана системой частиц) → Процессоры → Операции, которые сработали в данный момент

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

Вкладка «Производительность» в диспетчере задач

Чтобы понять, как оптимизируют графику в играх, нужно разобраться в том, как компьютер (или консоль) её воспроизводит. Сначала все модели, текстуры и другие графические ассеты с жёсткого диска загружаются в оперативную память для более быстрого доступа, а затем попадают в видеопамять, так как загрузка из неё ещё быстрее, чем из ОЗУ.

Но видеокарта работает быстрее, чем ассеты перемещаются в неё из оперативной памяти. Для того, чтобы избежать задержек из-за разницы в скоростях, небольшое количество ассетов изначально загружается в специально отведённую для этого область памяти видеокарты. Подробно об этом процессе можно прочитать в блоге VFX-художника Саймона Трюмплера — из студии Wild Sheeep (WiLD Мишеля Анселя).

В основном оптимизация графики строится на «умной» подгрузке данных. Например, в играх с открытым миром нет смысла загружать весь уровень в память видеокарты. Вместо этого можно брать лишь те его части, с которыми взаимодействует игрок. В Insomniac Games разделили Манхэттен из Marvel’s Spider-Man на квадраты, и одновременно полностью в память загружалась только область квадратов 3×3 вокруг игрока.

GDC 2019

Похожим образом устроена система прогрузки карты в Minecraft. В зависимости от того, какое значение дальности прорисовки выбрал игрок, в оперативную память подгружается определённое количество так называемых чанков — областей уровня 16 на 16 блоков. И чем выше дальность прорисовки, тем больше чанков вокруг себя видит игрок.

Высокая дальность прорисовки — видны горы вдали

Низкая дальность прорисовки — недостаток чанков скрывается туманом

На производительность игры влияет то, как быстро строится каждый кадр. Скорость же построения зависит от количества «вызовов отрисовки», или Draw Calls. Один Draw Call — это одна графическая команда отрисовки, или набор параметров данного кадра, вроде необходимых объектов и текстур, которые отправляются в видеокарту для отображения на экране.

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

Источник цитаты: school-xyz.com

Чтобы сократить количество необходимых «вызовов отрисовки», разработчики Halo 4 использовали окклюжн-карты. Это такие плоскости, которые закрывают объекты вдалеке — вместо их прямого показа они как бы проецируются на плоскость с помощью шейдера. А когда игрок подходит вплотную, карта «испаряется», и только тогда за ней действительно что-то появляется. Такие шейдеры помогли сэкономить draw calls.

GDC 2014

Один из распространённых способов графической оптимизации — батчинг. Это объединение разных объектов в один для того, чтобы сократить количество «вызовов отрисовки» и отрисовать все «сшитые» объекты разом.

Различают статический и динамический батчинг. При динамическом батчинге движок сам определяет, какие объекты может «сшить», исходя из их геометрии и других схожих параметров. Он хорошо работает с объектами, которые разделяются во время игры — например, с осколками разрушенной стены. А параметры статического батчинга нужно задавать в движке заранее — для этого отмечают объекты, которые не будут меняться в игровом процессе.

Хороший пример динамического батчинга показал инди-разработчик Вигард Майклбаст. Он поместил на сцену в Unity 1200 болванчиков, и с помощью «сшивания» сэкономил почти 8000 «вызовов отрисовки», оставив всего 70 из них. При этом он достиг почти 30 FPS на не самой мощной встроенной видеокарте Intel.

Изначально вызовов отрисовке было больше, чем самих болванчиков, из-за того, что они были анимированы

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

Такой подход можно совместить с батчингом, так как сшивать можно только объекты с одной текстурой или материалом. Если несколько мешей «окрашиваются» согласно одному атласу, то их можно объединить.

Texture Atlas из Cuphead

В открытых мирах количество графических ассетов может легко перевалить за несколько тысяч, и контролировать поведение каждого из них очень сложно. Разработчики «Ведьмака 3» подошли к проблеме основательно — в студии создали отдельную базу данных для всех ассетов в игре. Такая база чем-то похожа на профайлер, речь о котором шла выше. В неё они сохраняли название объектов, количество полигонов и уровень детализации.

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

Такой редактор позволил CD Projekt RED избавиться от случайных ошибок и слишком затратных моделей. С помощью этой базы разработчики смогли найти тестовые сферы, которые забыли убрать из игры, и анимированные луки, которые почему-то оказались под землёй.

Помимо таких небольших ошибок встречались и масштабные странности — например, источник света радиусом четыре километра для создания теней. Но самая известная находка — это, конечно, ведёрко для яиц, которое состояло из полутора миллионов полигонов! Для сравнения, одна из «оболочек» из недавней Mortal Shell состоит всего из ста тысяч полигонов при гораздо большем количестве мелких деталей.

Упомянутый «уровень детализации», или LOD (Level Of Detail) — ещё один способ оптимизации 3D-ассетов. Это упрощённый меш трёхмерного объекта для его отображения издалека. Нет смысла отрисовывать сложный рельеф условной скалы, если игрок находится в километре от неё — вместо этого можно подгрузить один из её LOD-ов. Впрочем, увлекаться «уровнями детализации» не стоит — на хранение каждого из них потребуется память.

Обычно используют четыре уровня детализации. LOD-0 — это оригинальная модель, а LOD-3 — дальняя. LOD4 может быть просто 2D спрайтом, который всегда смотрит на игрока.

Источник цитаты: school-xyz.com

Пример LOD-ов бочки

Чуть более детально мы рассматривали оптимизацию 3D-моделей в отдельном материале.

При портировании, например, с iOS на ПК или консоли картинка не пострадает. Даже наоборот — при переносе игр с консолей на ПК игроки могут получить более гибкие настройки графики или повышенное разрешение, как в случае с портами Red Dead Redemption 2 и Horizon Zero Dawn.

Другой случай — портирование игры на более слабое железо, например, на Nintendo Switch. При создании порта The Witcher 3 на гибридную консоль разработчики из Saber взяли за основу версию игры для PlayStation 4, так как её быстрее всего смогли запустить на Switch. По словам разработчиков, при портировании нужно всегда отталкиваться от той версии, которую проще всего оценить на целевой платформе, чтобы сразу понять, над какими аспектами игры потребуется дополнительная работа.

The Witcher 3: Wild Hunt (Nintendo Switch)

Иногда при портировании можно избавиться от бесполезных на данной платформе возможностей. Например, Ларс Дусе при портировании переиздания своей игры Defender’s Quest на PS Vita столкнулся с тем, что режим графики из оригинальной игры и HD-режим на портативной консоли смотрелись почти одинаково, так что разработчик вырезал из порта режим высокого разрешения.

Defender’s Quest: Valley of the Forgotten (DX edition)

Когда речь идёт о портативных консолях, часто под нож идут эффекты постобработки. Например, во многих портах на Nintendo Switch, будь то AAA вроде The Witcher 3 или инди вроде Pumpkin Jack сглаживание либо присутствует в урезанном виде, либо отсутствует вовсе. То же самое происходит и с дальностью прорисовки — как правило, на консолях она гораздо ниже, чем на ПК.

Также в консольных портах часто используют заблокированную частоту кадров и динамическое разрешение. Разрешение сильно влияет на производительность игр, так что в трудных местах вроде людных городских площадей его можно понизить, а поверх рендерить интерфейс в базовом разрешении — это особенно хорошо заметно в том же «Ведьмаке» на Switch. Заблокированная же частота кадров помогает обеспечить стабильную производительность на консолях с учётом их более слабой по сравнению с ПК «начинки».

А разработчики Unity советуют избегать использование тесселяции в консольных портах. Тесселяция — это процесс автоматического «дополнения» полигональной сетки. Разработчики из WB Games Montreal столкнулись с проблемой использования этой техники во время разработки Batman: Arkham Origins — подробнее мы писали об этом в тексте про погоду в играх. Если на ПК тесселяция работает хорошо, то консольное железо может не справиться — в WB Games в качестве альтернативы использовали шейдеры. К тому же, чаще всего тесселяцию применяют при работе с природным ландшафтом, которого в Готэме немного.

Комментарии: 0