Глубокое погружение в FBX
FBX (Filmbox) — формат хранения 3д-контента. Поддерживается всем современным софтом, например: Maya, Blender, 3ds Max, Houdini, Cascadeur. Является стандартом индустрии разработки игр. Этот формат разработала компания Autodesk.
Файлы FBX бывают разных версий: бинарные или ascii.
На практических примерах в Maya и Unreal Engine мы разберём внутреннее устройство ASCII-FBX и подумаем над оптимизацией моделей и анимаций. Как они влияют на производительность и итоговый размер проекта.
(Проблема: бинарный fbx - это черный ящик, и сложно сказать что внутри. Из-за лицензии GPL разработчикам софта не-Autodesk сложно реализовать полную поддержку. FBX из Блендера может не открываться в Майе и наоборот.)
FBX может хранить : геометрию (массивы вершин, нормалей, uv), анимацию (массивы костей и весов костей, блендшейпы), скелеты, настройки материалов, текстуры (jpg/png/tga), камеры, световые источники и многое другое.
## Часть 1: Анатомия FBX. Разбираем файл на примере простой геометрии
ASCII-FBX - это текстовый не сжатый формат. Простые Binary FBX обычно гораздо меньше по размеру, поэтому не нужно использовать ASCII-FBX формат в реальной разработке!
Получился файл SM_CubeLikeHouse.fbx - 19 Kb на жестком диске. Открываем его в текстовом редакторе Notepad++, видим 458 строчек. Файл по структуре чем-то напоминает json или xml.
Сам этот текстовый файл очень большой из-за технической избыточной информации, поэтому проматываем вниз. В разделе Objects была создана полигональная сетка (Geometry), состоящая из массива Вершин, Нормалей, из Материала со свойствами, Оси, Параметры Location, Rotation, Scale сцены и объекта и т.д.
Это наш Статический Меш (в терминологии Unreal Engine).
Vertices и PolygonVertexIndex - это два массива, по которым собирается модель. Первый квад (4 вертекса соединенных гранями) рисуется по точкам 0, 1, 2, 4, второй квад рисуется по точкам 4, 5, 6, 7 и так далее. Но Анриал у нас рисует треугольниками, а не квадами. Поэтому Анриал будет брать для первого треугольника 0, 1, 2 вертексы, для второго треугольника 3, 4, 5 вертексы и так далее. Отображение полигональной сетки на экране называется Шейдинг.
Не весь софт работает как Майя или Анриал, иногда для отображения треугольников выбирается другой порядок вершин. Например, вы делали модель в Blender, развертку UV в Houdini, а текстурили в Quixel Mixer, возможны ошибки в наложении текстур и шейдинге. Чтобы избежать таких проблем желательно триангулировать модель до экспорта, и хранить 2 исходных версии модели - полигоны квадами и триангулированная.
По умолчанию сразу включилась поддержка Нанитов. Автоматически был создан простой материал с настройками из fbx-секции Material. Автоматически как-то была сделана не точная коллизия.
В момент импорта в Анриал FBX был преобразован в формат UAsset - это бинарный формат Unreal Engine.
В этой полигональной сетке домика - 20 треугольников. В памяти Анриала 70.7 Кб, в то время как исходный ASCII-FBX весил 19 Кб.
Когда вы будете собирать (Build) проект, то все ассеты будут переупакованы в процессе подготовки ассетов Cooking (Кукинг, не переводится).
Когда мы назначим материал, размер модели вырастет до 1.8 Мб.
ASCII-FBX - 19 Кб
UAsset - 70.7 Кб
## Часть 2: Усложняем геометрию. Материалы, Vertex Color, Transform
Получился файл SM_CubeLikeHouse2.fbx размером 24 Кб. Если открыть его в текстовом редакторе, то обнаружим 412 строк.
ASCII-FBX - 24 Кб
UAsset - 78.7 Кб
## Часть 3: Физика в FBX. UBX (Collision) и сокеты (Socket)
Сокеты в Статик Меши можно добавить через любой легковесный объект, например, Локатор (Locator, иконка - снежинка). Разместить эти локаторы в 3д пространстве и сделать Пэрентами основного меша.
Эти объекты должны называться SOCKET_Какое-тоНазваниеСокета. И конечно же никакого русского языка и никаких спец-символов.
Simple Collision в Статик Меши так же вручную можно смоделировать и добавить. Иногда это проще, чем создавать коллизию в Анриале. Я использовал Box-форму и Convex-форму для сложного замкнутого контура крыши. Этим мешам желательно удалить UV.
Такие меши Должны называться UBX_ОригинальныйМеш_01, UBX_ОригинальныйМеш_02, UCX_ОригинальныйМеш_03. Теперь Анриал сможет автоматически загрузить эту коллизию.
Более детально можно прочитать в официальной документации:
Получился файл SM_CubeLikeHouse3.fbx размером 32 Кб.
ASCII-FBX - 32 Кб
UAsset - 88.7 Кб
## Часть 4: Embed media
Получился файл SM_CubeLikeHouse4.fbx размером 164 Кб. В этом файлике всего 562 строчки, но появился блок с упакованными картинками.
Иногда удобны Embed Media встроенные в FBX. Например, в тех случаях, когда эту модель больше не нужно редактировать. Удобно такую модель загрузить на сайт Mixamo для поиска подходящих анимаций.
Иногда это не удобно, когда модель нужно доработать, перескинить, переделать Morph Target, или что-то еще.
## Часть 5: Скелет и анимация
Кости скелета управляют вершинами полигональной сетки - это скелетная анимация.
Скининг (Skinning, не переводится) - это процесс назначения костям (Bones) относительных весов (Weight) для трансформации вершин (Vertex).
Главная кость скелета обычно называется root (рут, не переводится).
Риг - это управляющая конструкция для скелета. Что-то вроде дополнительного упрощенного скелета, которым пользуются аниматоры. Риггинг (Rigging, не переводится) это процесс разработки управляющей конструкции.
Физические ассеты сейчас не переносятся из Майи в Анриал. Риги обычно остаются в программе моделирования и не экспортируются, а в Анриале создаются свои собственные риги.
SK_AnimatedCubeLikeHouse.fbx размером 28 Кб.
Мы можем вместе с моделью в одном FBX-файле хранить не только меш, скелет, но и анимацию, и даже десятки анимаций. Но лучше отдельно под каждую анимацию создавать отдельный FBX, без меша. Во-первых, это экономия места на диске, во-вторых, удобнее работать в командной разработке игры, в-третьих, редактирование 1 анимации в контейнере состоящем из 50 анимаций и меша - это адское мучение.
1 анимация = 1 файл.
Открываем FBX в текстовом редакторе.
В разделе Connections мы видим все объекты FBX-файла, и как они друг с другом связаны
ASCII-FBX - 28 Кб
UAsset SKM - 98.8 Кб
UAsset Skeleton (3 кости) - 6.6 Кб
## Часть 6: Стандартный скелет Unreal Engine
FBX -1 Мб
UAsset (меш) - 8.1 Мб
UAsset (68 костей) - 23.5 Кб
FBX - 3.2 Мб
UAsset (меш) - 18.9 Мб
UAsset (161 кость) - 215.2 Кб
FBX - 519 Кб
UAsset (меш) - 2.3 Мб
UAsset (88 костей) - 101.2 Кб
Сравним персонажей:
Персонаж - Mannequin - UEFN - Manny
Костей - 68 - 88 - 161
UAsset - 8.1 Мб - 2.3 Мб - 18.9 Мб
Memory - 11.6 Мб - 9.2 Мб - 65.6 Мб
В трипл-эй студиях, например, Epic Games или CD Project Red, могут себе позволить использовать высокополигональные меши. Например, вот персонаж Twin Blast из игры Paragon. В этом персонаже 204 кости, около 100к полигонов, и 15 слотов Материалов. Paragon - сетевая игра для консоли Play Station 4. Одновременно в этой игре было 10 таких высокодетализированных персонажей и эта игра не тормозила на старой консоли. Инди-разработчикам не всегда удается добиться такой оптимизации.
## Часть 7: Анимация
Экспортирую из Анриала анимацию Slide для скелета UEFN
FBX - 2.1 Мб
UAsset - 2.5 Мб
Frames - 300
Length = 10s
Frame Rate = 30
Выполняю упрощение кривых, удаление лишних ключей.
Это простой пример оптимизации уже оптимизированной анимации. Но если использовать Мокап-анимации, или анимации из Маркет-Плейсов, то могут быть сильно не-оптимизированные, не синхронизированные по FPS анимации.
Итак, представим ситуацию, что вы разрабатываете игру, берете ассеты Мегасканс с миллионами полигонов, берете текстуры 8к, чтобы было красивее, и берете мокап-анимации для анимации моделей. Можно ли уложиться в целевой размер билда игры 40 Гб? Да, можно, только это сложно.
Меня на эту статью подтолкнуло видео от Sandfall Interactive на канале Unreal Engine: