Моя первая за последние 12 лет статья на Хабрахабре «The Goddess's Will — или почему никто не делает видеоигры в стиле пререндеренного 3D, а мы делаем одну такую» понравилась комьюнити Хабра. Спасибо вам за высокую оценку нашей работы! Было много интересных вопросов и тёплых пожеланий в комментариях. На большинство я ответил сразу, но некоторые вопросы требовали много времени и усердия, чтобы обстоятельно на них ответить на месте, поэтому я решил включить эти ответы в конец новой статьи о проблемах в разработке графики TGW. Если интересно почитать именно разбор комментариев, можете перейти по оглавлению сразу к теме ЧАВО.

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

Содержание

Внимание!

Быстроновости по The Goddess's Will.
С прошлой нашей встречи у нас многое изменилось: мы собрали почти 2000 вишлистов? за пару недель, и теперь спешим показать вам свежий геймплейный трейлер The Goddess's Will. Это трейлер нашего технического демо, но мы добавили туда щепотку нарративного контекста, чтобы поведать чуть больше о завязке сюжета. Прошу!?

Не забудьте поставить лайк и подписаться на канал. У Imagine Tavern будут появляться новые видео в ближайшем будущем?

А если интересно узнать больше о нашем проекте в Steam, то заходите к нам в Telegram или на саб-Reddit.


Работа с графикой

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

Когда мы хотим начать работать с пререндеренной графикой, первым делом возникает вопрос: а что это такое — этот ваш пререндер, и нужен ли он нам вообще, чтобы с ним связываться? Историю пререндера в очень обобщенном виде я описал в предыдущей статье. Но вкратце напомню: пререндер — это когда 3D‑сцена или анимация рендерится заранее на мощной станции, а результирующее изображение используется в конечном продукте.

Пререндер в видеоиграх изначально был призван обогатить визуал продукта за счет нового модного 3D в условиях, когда этот модный новый 3D не мог достаточно гладко воспроизводиться в реальном времени на доступном железе тех лет. 3D‑объекты и анимации этих объектов рендерили на мощных станциях типа SGI Indigo/Octane/Onyx.

Удовольствие в те времена это было точно недешевое. Например, Octane стоил порядка 10к долларов на тот момент, но даже такой сетап мог выводить одну сцену
для Resident Evil 3 несколько дней.

Рис 0. Реклама Octane. Видео с YouTube-канала The Retro Collective
Рис 0. Реклама Octane. Видео с YouTube-канала The Retro Collective

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

В какой-то момент в ходе разработки возникают вопросы:

  • Как готовить модель к процедуре рендера?

  • Как выставить правильный свет, чтобы графика в игре не выглядела неприятно бликующей или затемненной?

  • Под каким углом поставить камеры и сколько их нужно, чтобы добиться красивого 2.5D изометрического вида?

  • Почему после очередного нажатия кнопки рендера на выходе мы вдруг получили усеянное черными точками месиво?

  • Какая постобработка необходима для улучшения качества, а какая будет только мешать и тратить время?

  • Хорошо, мы вывели необходимые статические объекты и анимации. Почему игра неистово тормозит и статтерит?

  • Откуда из 500 MB упакованной графики берутся сожранные 12 GB видеопамяти в рантайме?

  • И главный вопрос — где чёрт возьми, взять столько времени, чтобы дождаться очередной прогонки запоротого ранее рендера?

Далее мы рассмотрим процесс создания графики для нашего проекта и параллельно ответим в свободной манере на эти вопросы. Для большего увеселения мы затронем не только технические вопросы, но и творческие моменты. Держу пари, это тоже будет интересно. Первый из основных вызовов в разработке графики для The Goddess's Will это создание статичных объектов в пререндере. С него и начнем.

Создание статичных объектов или зачем нам рисунок камня?

Статичные объекты (как и любые другие объекты), такие как камни, скалы, кувшины, элементы забора, стеллы и прочее, должны отображаться под задуманным углом камеры относительно поверхности. Какой угол выбрать? Традиционная изометрия ориентируется примерно на 33 градуса, но мы решили сделать игру чуть более кинематографичной и современной, и выбрали стандартом 50 градусов. Расположенная чуть ниже ожидаемого в изометрии, камера дает больше ощущения глубины сцены. Таким образом, игра ясно отсылает на классику, но в деталях остается современной. Это важно, чтобы не просто слепо подражать технологиям предков, а выдавать свою интерпретацию.

Мы пробовали разные углы для отображения, например, вот пробы Nuunn Press под двумя близкими углами. Мы выбрали 50°, так как 55° дает нам слишком мало плоской поверхности, хотя и дает еще больше глубины картинке, и открывает интересные детали.

Рис 1. Nuunn Press в 55° (слева) и в каноничные теперь 50° (справа)
Рис 1. Nuunn Press в 55° (слева) и в каноничные теперь 50° (справа)

Причем выглядеть эти объекты должны хорошо именно под таким углом камеры (50°) — другой нам не нужен, чтобы не ломать перспективу. Поэтому еще только проектируя очередной элемент окружения мы уже думаем о том, как он будет смотреться «под наклоном». Теперь давайте пройдемся по основному порядку разработки на конкретном примере и последовательно.

С чего нам стоит начать? С простого — с камней. Если вы разрабатываете игру, то без камней никуда.

Рис 2. Камень я не дам
Рис 2. Камень я не дам

Для начала нужно создать скетч камня, чтобы точно понимать, каким мы хотим, чтобы он предстал перед зрителем на камере под наклоном в 50°. Учитываем контекст биома, над которым мы трудимся. В нашем случае это каменистое плато. Чтобы выбрать нужную нам форму, рисуем концепты камней на выбор. Не забываем использовать выбранную палитру биома и полезный для 3D‑художника вид сбоку!

Рис 3. "Каменюшки, камешки, каамни, каменюки, камни большие жестб."
Рис 3. "Каменюшки, камешки, каамни, каменюки, камни большие жестб."

Когда мы подготовили удачные концепты и покрасили их — моделим и текстурим наш камень полностью в 3D, чтобы все ракурсы совпадали с ракурсами, изображенными на концептах объекта. Это архиважно. Это наши «гарантированные» удачные ракурсы. Нужно отметить, что текстуры для моделей окружения стараемся подбирать более крупные, чтобы 1) они лучше смотрелись на отдаленной камере, 2) в перспективе было проще дорабатывать ассет в Photoshop.

Моделька есть. Водружаем каменюку на сцену с подготовленным светом. Тут главное, чтобы были правильно сбалансированы прямой и отраженный от пола свет, чтобы будущий элемент окружения не имел слишком глубоких теней и сохранял задуманный цвет текстуры.
Далее рендерим полученный камень с шестнадцати камер, расположенных на расстоянии 22.5° (360°/16) друг от друга на нашей рендер‑сцене. Выбираем лучшие ракурсы рендеров камня помимо «гарантированных», которые сохраняют приличную форму. Обычно выходит еще 3–4 дополнительных ракурса.

Выбранные ассеты аккуратно доводим в 2D, выравнивая тени, добавляя реалистичную неравномерность текстуре. Затем вписываем наш камень в наличествующие террейны (земля, трава, камень и др), чтобы размещение ассета было упрощено и посадка объекта в тайловую подложку была как можно более мягкой.

Рис 4. Камень невписанный в террейн (сверху), камень вписанный в террейн (снизу)
Рис 4. Камень невписанный в террейн (сверху), камень вписанный в террейн (снизу)

После полноценной доводки, камни попадают в движок путем обычного импорта ассетов — пока обойдемся без магии. При импорте такие объекты, как камни, мы оставляем в режиме VRAM Compressed, так как нам не понадобится получать доступ к их пикселям в рантайме, а небольшие артефакты совсем незаметны. Значит, можем сэкономить видеопамять! Каждый мегабайт нам очень пригодится. Для статичного одиночного объекта типа нашего камня достаточно будет просто уменьшить разрешение изображения до приемлемого и удалить щедрый прозрачный фартук.

Интерлюдия: Куда уходит память? Куда ушла она? Наверно, в край чудесный...

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

Приведу пример, чтобы объяснить сложный процесс простыми словами. У нас есть картинка камня. Большая такая пикча каменюки 1000×1000 пикселей весом 10KB: красивый камень на прозрачном фоне. Видеокарта загружает эту картинку в память для того, чтобы потом отобразить на экране. Однако процессу нет разницы отображать наш красивый камень, или его прозрачный фартук, процесс смотрит на разрешение изображения, и просто отображает каждый пиксель.

Таким образом, видеопамять работает с лишней незначимой для нас информацией прозрачного фона, так как любое изображение обрабатывается как прямоугольник. И камень, который весил 10 KB, после загрузки в видеопамять начинает весить уже порядка 3-4 MB! И это в случае, если мы готовы мириться с ухудшенным отображением сжатого камня с небольшими артефактами. А если мы дадим видеокарте команду распаковать картинку? Это может понадобиться, например, для обработки камня шейдерами. Тогда 10 KB могут превратиться уже, например, в 8MB добавив туда всякие служебные структуры и уровни детализации.

В этом нет большой проблемы, когда видеокарта имеет 10 GB памяти, а статичных объектов на сцене 20 штук. А что если у вас в распоряжении 2 GB видеопамяти, а объектов на сцене 2000 штук, и многие из них плавно анимированы? Это ведь Literally Unplayable! Если говорить строго, то большие сбросы информации в видеопамять оборачиваются выгрузкой данных в оперативную память, и как следствие, тормозами игры.

Береги платье снову, а видеопамять смолоду.

Рис 5. Последнее китайское предупреждение
Рис 5. Последнее китайское предупреждение

Создание анимированных объектов или бум растениеводства

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

Рис 6. Растения оказывают сопротивление озомбевшим девелоперам
Рис 6. Растения оказывают сопротивление озомбевшим девелоперам

Честно говоря, растения для нас это больная тема. На их производстве много копий было сломано и правок в Miro было выписано целый вагон. Точно больше, чем на персонажах.
Для начала двинемся тем же путем. Создадим концепт‑арты всех требуемых нам растений чтобы точно быть уверенными, что должно получиться в итоге.

У нас даже появился внутренний мем в рабочем чате
Рис 6.5. Мем вообще не оскорбительный, а самый настоящий жизненный
Рис 6.5. Мем вообще не оскорбительный, а самый настоящий жизненный
Рис 7. Растения рисуем видом сбоку - так проще моделировать
Рис 7. Растения рисуем видом сбоку — так проще моделировать

Дальше идет фаза моделирования деревьев и кустов в 3D. Что‑то приходится создавать в специализированных программах для работы с растительностью, а потом дорабатывать до совпадения с концептом в Blender. А что‑то, что вообще не имеет типовой растительной базы, приходится с нуля лепить в 3D.

Рис 8. Деревья во вьюпорте не покрутишь - чуда не произойдет
Рис 8. Деревья во вьюпорте не покрутишь — чуда не произойдет

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

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

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

Этого могло быть достаточно, но картинки, сжатые под свой фактический размер на экране мыльноваты из‑за смешения пикселей при сжатии, поэтому обычно мы упаковываем растительность в 150% от необходимого нам на сцене и уже в движке уменьшаем масштаб на 50%. Таким образом растительность получается более четкая, без лишнего мыла.

Рис 9. На плато цветочки должны уметь выживать в неблагоприятном климате. Раскадровка анимации "покачивание"
Рис 9. На плато цветочки должны уметь выживать в неблагоприятном климате. Раскадровка анимации "покачивание"

Теперь встает вопрос об импорте спрайтшита в движок. Godot по умолчанию не может знать, как расположена сетка объектов на картинке (ведь она не всегда матричная) поэтому нам пригодится map‑файл, который в формате JSON хранит позицию верхнего левого угла каждого изображения, размер кадра и угол поворота. Имея на руках такие данные, мы сможем без проблем транслировать спрайтшит во внутригодотовскую анимацию, которую можно проигрывать по кадрам как душе угодно.

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

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

Теперь, используя один из многих наших кастомных плагинов для Godot «Import Plus»? мы загружаем пак спрайтшитов растительности в движок, после чего в assets нас ожидают уже готовые .tres анимации.

Создание персонажей или на золотом крыльце сидели...

Самый сложный процесс проходят персонажи. Сначала всё как обычно, но с пристрастием.

По текстовому ТЗ с обилием сюжета и лора мы создаем концепт‑арты героя, чтобы разобраться, что из себя представляет новый персонаж на деле. Стараемся следовать лорным и сюжетным деталям, чтобы внешний вид героя не противоречил, а, наоборот дополнял картину мира и подчеркивал его роль в повествовании. Даже если это обычный стражник.

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

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

Рис 10. Галь. От первых эскизов до финального концепт-арта
Рис 10. Галь. От первых эскизов до финального концепт-арта

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

Когда модель завершена, у нас есть возможность полноценно посмотреть, как персонаж будет выглядеть в нужном размере под нужным углом на террейне. Если что‑то идет не так, то модель еще можно относительно безболезненно поправить. После того как мы удостоверились, что всё отлично, проводим ретопологию (много боли). Затем приступаем к покраске.

Рис 11. Смотр угла на террейне. Подходит? Или ошиблись с расчетами?
Рис 11. Смотр угла на террейне. Подходит? Или ошиблись с расчетами?

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

____HIDDEN_MEME____
Рис 12. Стадии подготовки персонажа. К сожалению, грубо покрашенной Галь не осталось?
Рис 12. Стадии подготовки персонажа. К сожалению, грубо покрашенной Галь не осталось?

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

Этап анимирования начинается с подробного ТЗ: как должен двигаться персонаж. Сюда тоже входит краткое описание его истории, характера, особенностей боди‑механики и поведения в целом. Замученный жизнью Фиолетовый Раб не должен двигаться как Джеймс Бонд (разве что как в последнем фильме), а юная лучница Галь не должна быть близка к Леголасу по уровню акробатики.

Для каждого из персонажей есть стандартный набор анимаций: ожидание боя, безмятежность, смерть, шаг, бег и так далее. Но для каждого персонажа есть и немалый набор уникальных анимаций, доступных только ему/ей.
Все анимации описаны в ТЗ, и аниматор уже может создать грубые наброски, чтобы команда могла посмотреть, как движется новооживленный. Обычно мы отсматриваем анимации прямо на live‑трансляции в Discord. Помните наши знаменитые 10-часовые созвоны? Так вот, это их часть.

После этого мы составляем правки, которые корректируют увиденное поведение, и обычно призваны улучшить импакт от атак, драматизм смерти, отыгрыш конкретной эмоции и так далее. Одним из самых важных параметров является хорошее отображение на 8–16 ракурсах камер. Мы не раз встречали ситуации, когда действие персонажа хорошо просматривается с 7 камер. А на восьмой движение абсолютно нечитаемо. Приходится править так, чтобы движение можно было ясно читать с каждой из 8 камер (для передвижения это 16 камер), что иногда приводит к серьезным правкам.

И так, итерационно, шаг за шагом, пока мы не придем к мнению, что анимации персонажа готовы и их можно рендерить в спрайты.

Рис 13. Girls just wanna have fun
Рис 13. Girls just wanna have fun

Далее, анимации следует отрендерить на подготовленной сцене с дефолтным светом, как мы это делали для статичных объектов и растительности.
И, конечно же, не забыть сделать портрет персонажа для IDE.
Порядок должен быть и снаружи, и внутри?

Рис 14. Наконец-то. Добавляем спавнеры на сцену!
Рис 14. Наконец-то. Добавляем спавнеры на сцену!

О бесшовности
Обычно мы держимся 8–16 направлений для анимаций: 16 для передвижения и 8 для статичных позиций. Одним из главных требований для анимаций у нас идет возможность бесшовно соединять одно движение в другое. Не всегда удается сделать совершенно бесшовный коннект — это всё же видео игра, где движения могут сменяться как угодно, а смешивания анимаций как в 3D у нас под рукой нет. Но зачастую всё идет хорошо. Для того чтобы добиться бесшовности обычно мы начинаем и заканчиваем каждую новую анимацию стандартным кадром "ожидание боя", но иногда приходится делать переходные анимации, которые мягко подводят персонажа к нужной позиции.

Теперь, из рендера мы получили набор отдельных кадров для разных направлений и нам нужен упакованный спрайтшит. Размер самой текстуры для импорта тоже нужно учитывать, поэтому сложить все картинки на один шит не выйдет. Godot 4 поддерживает размер 16384×16384 пикселей, и ни пикселем более. Иначе IDE при старте будет просто крашиться.

Пришло время поговорить о вариантах укладки кадров.

Насколько надежна ваша укладка?

Из опыта изучения вариантов размещения спрайтов на полотне спрайтшита, мы можем выделить 5 базовых типов. Вот они сверху вниз.

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

Рис 15. Базовая укладка квадратами
Рис 15. Базовая укладка квадратами

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

Рис 16. Сетка обрезанных прямоугольников
Рис 16. Сетка обрезанных прямоугольников

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

Рис 17. Сетка прямоугольников с поворотом
Рис 17. Сетка прямоугольников с поворотом

Полигональная укладка
Кадры описываются не прямоугольником, а набором полигонов. В теории, свободного места на спрайтшите должно становиться еще меньше. Картинки должны прилегать друг к другу очень плотно. Это в теории. Однако трудно найти хороший алгоритм для такой укладки. Пока что по проценту свободного места она либо равна, либо даже чуть‑чуть уступает предыдущему варианту с поворотом. И вдобавок еще один минус — разбирать такую укладку тяжелее, чем просто вырезать прямоугольники.

Рис 18. Полигональная укладка
Рис 18. Полигональная укладка

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

Рис 19. Концепция мозаичной укладки от Леди Анны
Рис 19. Концепция мозаичной укладки от Леди Анны

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

Метатехнология: паршл(частичный)-рендер

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

Рис 20. Освальд лишился левой руки во благо Империи паршл-рендера
Рис 20. Освальд лишился левой руки во благо Империи паршл-рендера

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

  1. Потребление видеопамяти падает на десятки процентов.

  2. Появляется вариативность сборки персонажей и окружения.

Мы прошли занимательный путь от страшных 12 GB в окошке потребления ресурсов GPU, до 1 GB видеопамяти на сцену, когда стали применять все найденные нами уловки.

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

Автоматизация процесса

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

  • Обобщенные сцены для рендера персонажей в Blender.

  • Вывод результатов рендера в унифицированном виде.

  • Упаковка результатов рендера в спрайтшиты.

  • Упаковка спрайтшитов в SpriteFrames.tres это ресурс Godot(движок спокойно запускается headless).

Таким образом, на CI/CD‑сервере мы можем прогонять полную процедуру вывода анимаций в удобный для проигрывания контейнер движка. От нажатия кнопки "Рендер" до выгрузки результатов уже в Godot.

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

Рис 21. Работают роботы - счастлив человек
Рис 21. Работают роботы - счастлив человек

На этом можно завершить овервью по этапам производства графики для The Goddess's Will. Осталось еще несколько интересных моментов: например, создание террейна (отрисовка, фотобашинг, выведение текстур), работа анимационного движка, проблемы с перепадами высот и прочее, но хронометраж текста и без того уже зашкаливает. Обсудим эти вещи в следующей статье.

Давайте перейдем к ответам на темы в комментариях.

ЧАВО

"Зачем пользоваться устаревшей технологией пререндера, если можно эмулировать такой визуал в обычном 3D?"

Рис 22. WHY-Y-Y? В этой пикче скрыт глубокий смысл
Рис 22. WHY-Y-Y? В этой пикче скрыт глубокий смысл

Для удобства я объединил разные комментарии в один мета‑вопрос. И давайте начнем отвечать на него с конца.

Хочу сразу отметить: я не считаю, что чистое 3D или пререндер лучше друг друга.

Это просто разные инструменты для выражения визуальной идеи. У 3D сто и один плюс по отношению к пререндеру, но здесь речь идет о том, почему пререндер имеет право на жизнь сегодня.

Можно ли воссоздать визуал пререндеренных анимаций в традиционном 3D?

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

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

В случае с 3D нас ожидает сложный путь трейдофов. Повышаем детализацию? Повышаем системные требования? Новые материалы и свет? А потянет ли наш сетап такие нововведения?

Угол обзора и свет.
В случае пререндера мы собираем картинку именно под тот угол обзора, который нам нужен: выставляем откалиброванный свет. Смотрим на полученную анимацию, и сразу понятно, чего нам ждать в игре. Если кадр статичный, то можем доработать полученную картинку в фотошопе. А еще пререндер характеризуется застывшим на моделях светом, что кто‑то, конечно, может посчитать архаизмом, но другому глазу будет несомненно приятно. У нас в планах есть поработать с нормал‑мапами для кастомного освещения. Я думаю, это будет выглядеть совершенно волшебно?

Для 3D нам пришлось бы подготавливать всю эту работу к real time: источники освещения должны были бы быть закреплены за персонажами и объектами, и двигаться вместе с ними, чтобы воссоздавать эффект запеченного света. Или же нужно настроить материалы, чтобы те не бликовали, и мягко подсвечивали персонажа или объект, а на самой текстуре персонажа был бы уже отрисован свет. Честно говоря, мне даже сложно представить, как достичь нужного эффекта на 100%.

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

Рис 23. Красный порошок это как тортик
Рис 23. Красный порошок это как тортик

В real time нам пришлось бы приложить больше усилий, чтобы стабильно получать нужный результат — работать с физикой взрыва.

Работа с пространством.
Еще интересный момент, что пререндер (в целом, как и любое 2D), дает нам невероятную свободу в искажении реальности и геометрии сцены. Чего в 3D, несомненно, тоже можно добиться, но результат будет не таким стабильным и воспроизводимым.

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

Так что, по моему мнению, полностью заменить спрайтовое 2.5D на фиксированную камеру в 3D и «покадровые» анимации с фиксированным светом не получится. Приблизиться к такому результату несомненно можно, но не достичь его в полном объеме. Да и затратить придется много ресурсов, чтобы заставить 3D и работать по законам 2D.

Теперь давайте разберемся, устарела ли сама технология?

Пререндер устаревшая технология?

Очевидно, что данная технология непопулярна сегодня. Но я не считаю технологию пререндера устаревшей. Как минимум в той коннотации, которую обычно вкладывают называя что‑то устаревшим. Устаревшее — это что‑то, бывшее ранее в употреблении, но позже замененное чем‑то более совершенным. Но можно ли считать 3D более совершенной технологией, чем 2D? Конечно нет. Пререндер — ничего более, чем вариант 2D.

В рисованном 2D нам нужно создавать каждый кадр анимации или заднего фона отдельно. Ну, или при помощи небольших эльфов‑помощников. Создавая пререндер нам необходимо сначала создать 3D модели, а затем уже с ними работать. Это накладные расходы. Но они дают нам достаточную свободу в корректировании любых элементов визуала буквально на ходу. В трех измерениях проще поправить анимацию, и сразу посмотреть на результат, чем перерисовывать каждый раз каждый кадр. Выходит, пререндер лучше, чем рисованное «от руки» 2D? Тоже нет. Это просто разные подходы с разными этапами производства.
Но пререндер муторнее, признаю?‍?

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

Рис 24. Это я, хвалю пререндеры древности
Рис 24. Это я, хвалю пререндеры древности

"Сюжет в игре похож на сюжет в порнофильме: он должен быть, но не так уж важен"

В комментариях под прошлым постом вспоминали Джона Кармака и его знаменитую цитату:
Story in a game is like a story in a porn movie: expected to be there, but not that important.

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

Немного о контексте цитаты

Эта цитата появилась в 1993-м году, когда Id Software работали над DOOM, и была выделена Кушнером в его книге Masters of Doom.
Давайте заглянем в 1993-й год, и посмотрим, какие основные тренды игровой индустрии на тот момент можно выделить.

Первый тренд — это все еще аркадные залы, продвигающие спинномозговой геймплей с выкрученной на максимум сложностью и репетативностью игрового процесса. Движуха с аркадами началась где‑то в начале 70-х, и к началу 90-х длилась как минимум лет 15. То есть целое поколение игроков (в том числе и сам Кармак) было воспитано на эстетике: «Действуй! Прыгай, пока бочки не взорвались; стреляй, пока тебя не застрелили, жми на кнопку — или проиграешь.»

Рис 25. Золотая эпоха аркад уже кажется такой недосягаемой
Рис 25. Золотая эпоха аркад уже кажется такой недосягаемой

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

Теперь в безбрежном море видеоигр с геймплеем прямого противостояния игрока с игроком или игрока с монстром стали появляться довольно сюжетные игры, такие как серия Shin Megami Tensei, Myst (сюжет‑загадка), Day of the Tentacle, Ultima, Final Fantasy, King's Quest и многое другое. Эти тайтлы должны были привлечь игроков, которые параллельно с начисткой морд друзьям в Street Fighter интересовались и игровыми мирами с их увлекательными историями.

Рис 26. Такая ламповая камера Ультимы. Но выглядит обскурно
Рис 26. Такая ламповая камера Ультимы. Но выглядит обскурно

Третий тренд, который я хотел бы выделить, пусть и самый маленький на тот момент, растущий организм — игры‑симуляции. SimCity, или, например, Civilization представляли игровой процесс не как требование нажимать нужные кнопки в нужный момент, а как исследование законов виртуального мира, эксперименты с геймплейными системами игры, ответы на вопрос «А что будет, если я выстрою такую систему? Это будет работать?».

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

Рис 27. Узнали? Согласны?
Рис 27. Узнали? Согласны?

В 1993-м году, идея, что играм не нужен (или неважен) сюжет, уже была устаревшей. Это ведь мнение одного человека, который вырос в эпоху аркадных автоматов и будучи выдающимся программистом консолидировал свой опыт в революционный DOOM. Однако, если Кармак считал, что пицца Domino's отстой, это не значит, что вам не следует её есть. Тем более, что к 93-ему году Кодзима выпустил пару частей Metal Gear, Snatcher и Policenauts и он, к вашему сведению, делал каждую из своих революционных игр с куском пиццы Domino's во рту.

Может быть, когда мы видим глубокий сюжет в Need For Speed это может показаться странным. Но даже в случае, когда катсцены с персонажами, обсуждающими ваш опыт гонщика вызывают лишь испанский стыд, это происходит чаще по причине плохой актерской игры и ужасного сценария, но точно не по причине наличия такой сцены в целом.

Рис 28. После этой сюжетной сцены мотивация пройти игру становится ощутимой
Рис 28. После этой сюжетной сцены мотивация пройти игру становится ощутимой

А ведь есть ещё и лор

В 2025-м году лор игры как будто бы стал обязательной галочкой для каждой уважающей себя игры. Даже DOOM на своем пути обзавелся не только сюжетом, но и лором мира с ангелами, демонами и Аргент Д'Нуром. Что?

Рис 29. POV: команда добавляет в DOOM не только сюжет, но и "глубокий" лор. Лицо Кармака
Рис 29. POV: команда добавляет в DOOM не только сюжет, но и "глубокий" лор. Лицо Кармака

К сегодняшнему дню люди пришли к идее, что игре недостаточно быть просто увлекательной на экране, но игра должна увлекать людей и вне экрана. Чтобы обсуждения выходили за пределы геймплея и битв с боссами. Интересно, общий объем обсуждений на тему «сколько детей было у Гвина?» превзошел объем обсуждений на тему «В каком порядке убивать Орнштейна и Смауга?».

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

Держу пари, среди читателей есть те, кто знает лор Hollow Knight, но никогда в неё не играл, и она у них даже не куплена (если вы все еще не скипнули, и читаете эту статью — спасибо). Однако есть и те, кто прошел Hollow Knight на танцевальном коврике без потери хотя бы одной маски уроном, но даже не знает, про что в целом игра.
И это нормально.

Рис 30. Диалоги, диалоги, диалоги. Когда уже геймплей будет?
Рис 30. Диалоги, диалоги, диалоги. Когда уже геймплей будет?

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

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

"Зачем вы используете C# для разработки в Godot 4, если есть нативный GDScript?"

Технологические холивары иногда бывают более жаркими, нежели лорные войны. Давайте проясним основную мотивацию выбора именно такого стека технологий для The Goddess's Will.

Почему только Godot?

Первые шаги игры были сделаны на GameMaker (+GML). Но после того, как мы столкнулись с жесткими ограничениями движка вместе с нашими растущими аппетитами, мы решили мигрировать на Godot. Почему не Unity или Unreal Engine и еще больше, можно прочитать в моей предыдущей статье о разработке The Goddess's Will.

Вкратце: Godot 4 нас привлек нас первоклассной структурой сцены, где всё является нодой, открытым исходным кодом, сильным и заинтересованным комьюнити, исчерпывающей документацией и отсутствием легаси‑мусора. Также отсутствие всяких мутных лицензий это тоже всегда плюс.

Так все звезды и сошлись. Godot разрабатывается в хорошем темпе, мы тоже не отстаем, и обновляемся на каждую новую минорную версию или патч с ее выходом. В данный момент игра работает на C#13 / .NET 9 / Godot 4.5.1. Сейчас код игры превышает 80к строк: часть функций будет доступна в технодемо, остальные, пока что, заблокированы на недостающие ассеты.

Рис 31. Это сильнее меня
Рис 31. Это сильнее меня

Godot имеет в своем распоряжении динамично развивающийся язык GDScript. С каждым патчем и новой версией движка язык получает значимые обновления. Но для нас GDScript не выглядел хорошим выбором. И вот почему:

  • Строгая архитектура и удобный ООП‑дизайн — это важно. C# и традиция написания программ на нем дает хорошую базу для предсказуемой и чистой структуры кода.

  • Инструменты разработки: JetBrains Rider с глубоким отладчиком и hot reload решают массу сопутствующих проблем. Инструменты отладки GDScript всё еще оставляют желать лучшего.

  • Производительность (с оговорками). C# легко оптимизировать и эффективно работать с многопоточностью. Однако на вызовах к API Godot сишарп уступает GDScript, работающему нативно. Но узкие места в связке с Godot мы решаем разумным контролем доступа к нодам.

  • Экосистема.NET. Библиотеки и NuGet упрощают интеграцию сторонних библиотек. Готовых решений для GDScript не так много, и вряд ли они появятся в будущем в значимом объеме, так как это всё же встроенный в среду язык. Сомневаюсь, что он когда-либо вырвется вовне.

  • Единый стек и упрощённый найм. Найти хорошего программиста на C# проще, чем на GDScript, так как рынок шире, и специализация профессионалов глубже.

Также мы отказались и от смешанного подхода csharp + GDScript: это усложняет тестирование и расширение проекта, а также размывает технологический стек продукта. GDScript перспективен, но для серьёзного проекта C# сильно надежнее.

Есть еще один скрытый пункт приоритета сишарпа.
Рис Я запутался какой там номер уже
Рис Я запутался какой там номер уже

Это синтаксис.
Лично мне си-подобный синтаксис милее python-подобного.

Как мы поплатились

Основные проблемы, с которыми мы столкнулись в связи с нашим выбором:

  • Краши mono‑байндингов, из‑за которых приходится перезапускать редактор. Это постоянная головная боль, которую никак не устранят в Godot. Возможно, стоит бросить всё и попытаться изучить проблему глубже.

  • Необходимость более пристально следить за освобождением памяти Godot‑ресурсов.

  • Ограничения при создании плагинов, ведь часть функций IDE недоступна из C#.

Рис 32. Он всегда внезапен, суров и безжалостен
Рис 32. Он всегда внезапен, суров и безжалостен

Архитектура

На одном из ресурсов специалист задавал вопрос: какую архитектуру проекта мы используем? Отвечаю: мы используем подход, близкий к Clean Architecture с изолированными слоями логики + MVI‑shaped взаимодействие слоев.

Godot‑слой хранит адаптеры между API движка и логикой (View, Controller, Model и др).
POCO‑слой — это чистая бизнес‑логика на .NET 9: навыки, предметы, подсистемы механик.
Такое разделение повышает гибкость, упрощает тестирование и масштабирование и ускоряет онбординг. Подробнее об архитектуре проекта можно поговорить в отдельной статье.

Планы на Open Source

Мы работаем не только над TGW, но и готовим фундамент с инструментами для других разработчиков?

TGWEngine — движок: подсистемы анимации, звука, ИИ, сохранений и так далее. Он изолирован от контента и со временем станет Open Source, чтобы другие люди могли создавать свои пререндеренные проекты на базе наших разработок.

Когда конкретно?
Пока трудно сказать, но самые важные шаги в этом направлении уже сделаны: сепарация логики, чистые интерфейсы взаимодействия. А вот с документацией пока туго. Пока по оперативному плану, релиз TGWEngine на нашем GitHub произойдет вместе с релизом полной версии игры.

Рис 33. Open Source движок это лучше, чем поддержка модов? Я просто не в курсе.
Рис 33. Open Source движок это лучше, чем поддержка модов? Я просто не в курсе.

Заключение

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

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

Нам будет приятно, если вы оставите под этим постом комментарий со своими мыслями. Может, зададите какие-то вопросы.

Не забудьте заглянуть на нашу страницу в Steam, на наш прекрасный сайт и, конечно же, смотрите геймплейный трейлер The Goddess's Will!
А если пошарите нас друзьям и коллегам, то нам будет очень приятно!

Рис 34. Ребус напоследок ?
Рис 34. Ребус напоследок ?

ДО ВСТРЕЧИ В КОММЕНТАРИЯХ ;-)

Комментарии (2)


  1. Jijiki
    20.10.2025 06:20

    яркий пример частичного пререндера(потомучто там есть особенности рендера скининга) это Халфа и дум3(md5-specs-en) или квейк - там частично пререндеренные модельки, но скининг считается в момент рендера, угадайте с 1ой попытки как произвести полную оптимизацию скининга(даже в наше время даже с fbx анимациями), в целом классно, успехов вам


    1. Jijiki
      20.10.2025 06:20

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

      вот если интересно

      Скрытый текст