Почему 3D-модели такие тяжёлые?
Ваша модель незаметно становится тяжелее
Вы экспортировали GLB-файл — 10 МБ, всё вроде бы нормально. Открываете на телефоне: белый экран, заикания или даже краш.
На компьютере всё работает, а на телефоне взрывается. Это не ваша ошибка в коде. В этом заключается непростое свойство 3D-моделей: на диске и в VRAM они имеют совершенно разный размер.
JPG-изображение может весить всего 200 КБ на диске. Но GPU не понимает JPG; он понимает только сырые пиксели. Поэтому перед загрузкой в VRAM изображение полностью распаковывается. Текстура 2048x2048 занимает около 22 МБ VRAM после распаковки. Если использовать 6 текстур (альбедо, нормали, шероховатость, металличность, AO, эмиссия), одна модель занимает 132 МБ.
На телефоне может быть всего 2-4 ГБ VRAM, и текстуры одной модели занимают 3-6% от этого. А теперь представьте 10 моделей в сцене.
Разбираем: куда уходят байты
Типичная GLB-модель состоит из трёх основных частей: данные вершин, текстуры и метаданные с анимациями.
Возьмём реальную PBR-модель:
| Компонент | Что это | Типичная доля | Примечания |
|---|---|---|---|
| Текстуры | альбедо, нормали, шероховатость, металличность, AO и т.д. | 70-85% | Почти всегда основная часть |
| Данные вершин | координаты, нормали, UV, тангенты, цвет | 10-20% | Зависит от сложности модели |
| Данные анимации | скелеты, скинг, ключевые кадры | 0-15% | Только при наличии анимации |
| Прочее | определения материалов, структура сцены, камеры | < 2% | Пренебрежимо мало |
Текстуры занимают около 80%. Часто кажется, что нужно оптимизировать вершины, но на самом деле основное пространство съедают текстуры.
"Маленький на диске" не означает "маленький в VRAM"
Это, пожалуй, самый важный момент в понимании производительности 3D.
PNG и JPG разработаны для сетевой передачи — компактные на диске, быстрые для скачивания. Но GPU не может использовать их напрямую; их необходимо полностью распаковать в сырые пиксели. Формула:
VRAM = ширина * высота * 4 байта (RGBA) * 1.333 (с мипмапами)
Текстура 4096x4096 RGBA:
| Метрика | Значение |
|---|---|
| Размер PNG файла | ~8 МБ |
| Размер JPG файла | ~1.5 МБ |
| Использование VRAM (с мипмапами) | ~87 МБ |
JPG весом 1.5 МБ превращается в 87 МБ VRAM.
Что такое мипмапы? GPU генерирует серию постепенно уменьшающихся версий текстуры — от оригинального размера до 1x1 пикселя, каждый уровень вдвое меньше предыдущего. Это ускоряет и делает более чёткой отрисовку удалённых объектов, но требует примерно на 33% больше VRAM. Почти все 3D-приложения используют мипмапы, поэтому этот overhead является стандартом.
Таким образом, PNG и JPG — это как вакуумные пакеты для хранения: спрессованы для перевозки, но на месте нужно полностью развернуть. Скачивание ускорилось, но экономия VRAM: ноль.
Что происходит при нехватке VRAM
Вы не увидите аккуратного диалога «недостаточно памяти». Реальность хуже:
- Мобильные устройства: белый экран или ОС убивает вкладку целиком
- VR-шлемы: пропуск кадров. В VR пропущенный кадр — это не «немного подлагивает», а вызывает тошноту
- Десктоп: мерцание текстур, деградация, замедление рендеринга
На Reddit один разработчик создал WebXR-галерею и запихнул 60 стереоизображений на Quest. Сначала работало, но потом стало нестабильным и вылетело. Он потратил дни на отладку кода, прежде чем понял, что вообще не думал о VRAM — просто продолжал пихать JPG в GPU.
Два направления сжатия
Сжатие 3D-моделей делится на два направления:
Сжатие вершин — более компактное хранение геометрических данных (координаты вершин, нормали, UV). Например, замена 32-битных float на 16-битные целые (это называется квантизация). Типичные решения: Draco, MeshOpt, KHR_mesh_quantization.
Сжатие текстур — сохранение текстур в сжатом виде даже внутри VRAM. GPU распаковывает отдельные пиксели «на лету» при выборке, практически без потери производительности. Типичное решение: KTX2 + Basis Universal.
| Сжатие вершин | Сжатие текстур | |
|---|---|---|
| Что уменьшает | Геометрические данные | Текстуры |
| Типичный эффект | На 50-90% меньше | На 50-70% меньше на диске, на 75% меньше VRAM |
| Потеря качества? | Да, потеря точности | Да, потеря качества |
| Лучше всего подходит | Вершинно-ёмкие модели | Практически любая PBR-модель |
| Подробнее | Часть 2 | Части 3 и 4 |
Распространённое заблуждение: сжать вершины Draco и на этом остановиться. Но текстуры — это 80% размера модели. Уменьшите вершины вдвое, а общее уменьшение может составить всего 10%. Нужно работать в обоих направлениях.
Нет универсального метода
Это основной тезис всей серии:
Разные платформы, разные устройства, разные сценарии требуют разных стратегий сжатия.
| Сценарий | Основное ограничение | Приоритет |
|---|---|---|
| Десктопная веб-визуализация | Скорость загрузки | Размер файла |
| Мобильный браузер | VRAM | Сжатие текстур |
| VR-шлем | VRAM + частота кадров | Сжатие текстур + упрощение вершин |
| WeChat Mini Program | Размер пакета + совместимость | Лёгкие варианты (MeshOpt) |
| Крупные сцены | VRAM + draw calls | Полное сжатие + LOD |
Каждая следующая статья не просто скажет «используйте X и всё». Она объяснит: где X блестит, когда он даёт обратный эффект, и когда стоит обратиться к Y.
Что дальше
Эта статья закрепила проблему. Следующая будет практической — знакомство с тремя инструментами сжатия вершин: квантизация, MeshOpt и Draco.