Давненько я не писал. Дзен деградировал, информационной пользы никакой. Но как архив, может и сгодится. Эту тему пишу чисто для себя. С техническими подробностями. Типа, шпаргалка. Может когда и пригодится.
В настоящий момент делаю дополнение к игре The Pharody под названием Вальхалла. Герой путешествует по миру иному. А точнее по различным мирам. В том числе весьма необычным. С необычными обитателями. Когда я увидел модель космического котика, я был очарован и захотел пристроить такого симпатягу в один из этих миров. Модель бесплатная и в открытом доступе. Однако, халява почти всегда бывает коварна. Если не стоит денег, так отберёт у тебя другое. Например, время и нервы. Как и на этот раз. Котики прописаны в сценарий игры. Пришло время вставлять в игру саму модель. И... понеслось...
Исходная проблема: архитектурный диссонанс
Если коротко, то модель оказалась совершенно не адаптирована под контекст проекта. Напоминаю, разработку я веду на движке UE4. И модель не являлась ассетом соответствующего формата, а предлагалась, как есть.
А именно:
- Геометрия: единый меш в формате FBX.
- UV-развёртка: три логически разделённых области, соответствующие поверхностям шерсти, ткани одежды и рюкзака.
- Материалы: один универсальный материал, не содержащий ссылок на текстуры.
- Текстуры: три каталога (по 25 файлов в каждом), содержащих вариации для каждой из трёх поверхностей.
Такая организация создаёт архитектурный диссонанс: логическое разделение поверхностей в UV-пространстве не отражено в материальной системе. В классическом конвейере это потребовало бы разделения меша на три подмеша с привязкой отдельных материалов — операция, требующая вмешательства в исходную модель и нарушающая целостность ассета.
Но что будет, если я "распилю" меш на 3 части? Прежде всего для меня это сложно, ведь я больше программист, чем 3D художник. Результат будет красивыми по науке: 3 меша и 3 материала. И ложечка дёгтя бонус в виде доп. нагрузки на графику. Правда, совсем ничтожная. Но должен же быть минус, оправдывающий мою лень и обосновывающий иной подход.
Реализация: параметрическая система материалов
И я предпринял попытку решить проблему на уровне материала. Движок это позволяет. Но, т.к. я столкнулся с такой задачей впервой, пришлось копаться в справке и танцевать с бубном. Как говорится, хрен не слаще редьки. Либо пилишь меши, либо изобретаешь велосипед. Изобретать всё-же интереснее.
Создание материала и динамическое управление
- На основе анализа UV-развёртки были созданы три чёрно-белые текстуры-маски, каждая из которых выделяет одну из трёх логических областей. Эти маски объединены в 1 текстуру и раскиданы по 3 цветовым каналам: красный, зелёный, синий. Ещё и альфа остался. Он не нужен, но он есть. Да и красный, как видно из схемы, тоже остался не у дел.
- В конструкторе материалов был построен граф со структурой из 3 параметрических сэмплов, объявленных как Parameter с уникальными именами.
- Для управления вариациями был создан Material Instance, наследующий базовый материал. Через интерфейс инстанса доступны три параметра текстур, которые могут быть переопределены в рантайме.
- Загрузка текстур выполняется через ассет-референсы, организованные в структурированные папки контент-браузера с использованием SoftObjectPath для предотвращения избыточной загрузки в память.
Результаты и метрики
Реализованная система обеспечивает:
- Количество уникальных комбинаций: 25 × 25 × 25 = 15 625 вариантов персонажа.
- Производительность: Единый материал сохраняет один draw call на экземпляр персонажа. Современным машинам это как слону дробинка, хвастать нечем. Но я же преподношу свою игру как способную подниматься на дряхлом железе.
- Гибкость: Возможность замены текстур в рантайме без перекомпиляции шейдера или перезагрузки уровня.
- Поддерживаемость: Все вариации управляются через единую точку — параметры инстанса материала.
Выводы
Демонстрируемый кейс иллюстрирует принципиальный подход к работе с неидеальными ассетами: вместо попытки приведения входных данных к «идеальному» состоянию, я использовал возможности движка для создания адаптивной системы:
- Отказ от геометрической модификации в пользу шейдерной логики позволил сохранить целостность исходного ассета и упростить пайплайн импорта.
- Использование параметрических материалов превратило статичный недостаток (единый материал) в динамическое преимущество (рантайм-вариативность).
- Масочная композиция на уровне шейдера обеспечила визуальную корректность без увеличения стоимости рендеринга.
И вот у меня в песочнице бегают разноцветные котики. Осталось только перенести их в игру.