От Blender до продакшена: сквозное сжатие на практике
В этой серии мы уже разобрали инструменты, принципы и критерии выбора. В финальной статье соберём всё в работающий конвейер: возьмём реальную модель из Blender, будем сжимать её шаг за шагом, фиксируя изменения размера файла, видеопамяти и времени загрузки, и посмотрим, удастся ли превратить «толстяка» на 50 МБ в модель на 5 МБ, которая мгновенно открывается на телефоне.
Для кого: вы прочитали предыдущие 5 статей и готовы применять на практике. Здесь не будет новой теории — только готовые команды, скрипты и воспроизводимый процесс.
Отправная точка: реальная PBR-модель
Возьмём типичную модель для витрины интернет-магазина: высокополигональный продукт с полным набором PBR-текстур.
| Исходные показатели | Значение |
|---|---|
| Исходник Blender | ~120 МБ (включая неэкспортированную высокополигональную модель) |
| Экспорт в GLB (float32 + PNG) | ~50 МБ |
| Количество вершин | ~180 000 |
| Текстуры | 6 × 4096×4096 (albedo, normal, roughness, metallic, AO, emissive) |
| Видеопамять (все 6 в распакованном виде) | ~520 МБ |
| Цель | файл ≤ 5 МБ, контролируемая видеопамять, мгновенный запуск на мобильных |
Файл на 50 МБ и 520 МБ видеопамяти — такая модель гарантированно уронит мобильное устройство. Разбираем по шагам.
Шаг 0: правильный экспорт из Blender
Первый рубеж сжатия — это экспорт. Многие теряют здесь кучу времени и размера.
Ключевые настройки экспорта glTF из Blender:
- Формат:
glTF Binary (.glb)(один файл, удобно передавать) - Геометрия: включить
NormalsиTangents(для PBR-карт нормалей нужны касательные) - UV: убедиться, что экспортируются (по умолчанию включено)
- Текстуры:
AutomaticилиJPEG(формат на этом этапе не важен — пережмём позже, главное, чтобы они экспортировались) - Сжатие: не включать встроенное сжатие мешей Blender — используем более профессиональные инструменты
- Преобразования:
+Y Up(стандарт glTF) - Данные: экспортировать только нужное (анимации, камеры, свет не нужны — не экспортируем, экономим объём)
После экспорта model.glb: 50 МБ, 6 PNG-текстур, вершины float32. Это наша базовая точка.
Частая ошибка на этом шаге: Blender по умолчанию экспортирует неиспользуемые меши и скрытые вспомогательные объекты. Перед экспортом выполните
File > Clean Up > Purge Orphansи выберите в аутлайнере только нужные объекты.
Обзор сквозного конвейера
Нарисуем полную схему, чтобы видеть картину целиком:
Исходник Blender
│ Экспорт .glb (float32 + PNG) 50 МБ
▼
[1] Удаление лишнего + сварка дубликатов вершин (gltf-transform) ~45 МБ
│
[2] Сжатие вершин: MeshOpt (gltfpack / gltf-transform) ~30 МБ
│
[3] Сжатие текстур: PNG → KTX2 (ETC1S/UASTC) ~6 МБ
│
[4] (опционально) Упрощение геометрии LOD (simplify) ~4-5 МБ
▼
Итог: model-final.glb ~5 МБ
│
Загрузка в движок (Three.js / Babylon.js) → транскодирование на лету → продакшен
Каждый шаг отслеживается в таблицах ниже.
Инструменты: что выбрать
Инструментов сжатия несколько — сравним, чтобы не ошибиться:
| Инструмент | Сильные стороны | Слабые стороны | Подходит для |
|---|---|---|---|
| gltf-transform | Универсал: текстуры + вершины, API, скриптуемость | Максимальное сжатие уступает специализированным | Основной инструмент, большинство сценариев |
| gltfpack | Профи в сжатии вершин, нативная поддержка MeshOpt | Слабое сжатие текстур | Плотные вершины, нужен тонкий контроль MeshOpt |
| toktx | Максимально профессиональное сжатие текстур, все параметры | Только текстуры, не работает с моделью целиком | Тонкая настройка отдельных текстур |
| gltf-pipeline | Ветеран, поддержка Draco | Слабо поддерживается, мало функций | Старые проекты на Draco |
| Онлайн-инструменты (gltf.report) | Без установки | Не подходят для автоматизации и пакетной обработки | Эксперименты, разовые задачи |
Основная линия: gltf-transform для всего процесса, при необходимости gltfpack для вершин и toktx для отдельных текстур. Все шаги ниже основаны на gltf-transform.
Шаг 1: удаление лишнего + сварка
В моделях часто встречаются дубликаты вершин, неиспользуемые узлы и материалы. Сначала чистим.
gltf-transform optimize model.glb step1.glb --weld --prune
| Этап | Размер файла | Видеопамять | Изменение |
|---|---|---|---|
| Базовая точка | 50 МБ | ~520 МБ | — |
| Шаг 1: чистка | 45 МБ | ~520 МБ | -5 МБ (память не изменилась — текстуры на месте) |
Видеопамять почти не изменилась — это ожидаемо: чистка экономит вершины и структуру, а основной объём памяти занимают текстуры.
Шаг 2: сжатие вершин MeshOpt
gltf-transform optimize step1.glb step2.glb --meshopt --weld --prune
Флаг --meshopt квантует вершины до 16 бит и применяет lossless-кодирование MeshOpt, автоматически добавляя расширение EXT_meshopt_compression.
| Этап | Размер файла | Видеопамять | Изменение |
|---|---|---|---|
| Шаг 1 | 45 МБ | ~520 МБ | — |
| Шаг 2 + MeshOpt | 30 МБ | ~520 МБ | -15 МБ (часть вершин) |
Видеопамять всё ещё ~520 МБ? Верно — вершины занимают лишь 10–20% памяти, их сжатие мало влияет на общий объём. Настоящий пожиратель памяти — текстуры, и им займёмся на следующем шаге.
Шаг 3: сжатие текстур PNG → KTX2
Этот шаг даёт максимальную отдачу.
gltf-transform optimize step2.glb step3.glb \
--texture-compress basisu \
--meshopt --weld --prune
Флаг --texture-compress basisu автоматически определяет тип каждой текстуры: цветовые (albedo, emissive) — в ETC1S, data-текстуры (normal, roughness, metallic, AO) — в UASTC.
| Этап | Размер файла | Видеопамять | Изменение |
|---|---|---|---|
| Шаг 2 | 30 МБ | ~520 МБ | — |
| Шаг 3 + KTX2 | 6 МБ | ~70 МБ | -24 МБ файл / -450 МБ память |
Это переломный момент всего конвейера:
- Файл уменьшился с 30 до 6 МБ
- Видеопамять упала с 520 до ~70 МБ — шесть текстур 4096 превратились из «распакованных пикселей» в блоковое сжатие: каждая с ~87 МБ до ~11–14 МБ
Память снизилась на порядок — именно это определяет, запустится ли модель на мобильном устройстве.
Шаг 4: (опционально) упрощение геометрии
Если нужно ещё меньше, а сцена допускает снижение точности вершин, добавляем упрощение геометрии.
gltf-transform optimize step3.glb final.glb \
--texture-compress basisu \
--meshopt \
--simplify --simplify-ratio 0.5 \
--weld --prune
--simplify-ratio 0.5 означает сохранение примерно 50% вершин.
| Этап | Размер файла | Видеопамять | Изменение |
|---|---|---|---|
| Шаг 3 | 6 МБ | ~70 МБ | — |
| Шаг 4 + упрощение 0.5 | 4.5 МБ | ~70 МБ | -1.5 МБ (память почти без изменений) |
Упрощение в основном экономит размер файла, на память влияет слабо. Цена — снижение детализации: при близком рассмотрении будет заметно. Для витрин товаров обычно не рекомендуется чрезмерное упрощение, а вот для архитектуры и больших сцен — в самый раз.
Итоговая таблица эффективности
Сложим все четыре шага (на основе нашего примера; цифры иллюстрируют порядок величин):
| Шаг | Размер файла | Видеопамять | Суммарное снижение |
|---|---|---|---|
| Базовая точка (float32 + PNG) | 50 МБ | ~520 МБ | — |
| + чистка и сварка | 45 МБ | ~520 МБ | -10% |
| + MeshOpt для вершин | 30 МБ | ~520 МБ | -40% |
| + KTX2 для текстур | 6 МБ | ~70 МБ | -88% файл / -87% память |
| + упрощение геометрии (0.5) | 4.5 МБ | ~70 МБ | -91% файл |
Вывод: сжатие текстур даёт основной выигрыш и по объёму, и по памяти. Сжатие вершин — приятное дополнение, сжатие текстур — необходимость. Это полностью подтверждает тезис из первой статьи: текстуры занимают 80% объёма, и их оптимизация окупается больше всего.
Версия одной командой: для ленивых
Если не нужно смотреть по шагам, применяем всю оптимизацию сразу:
gltf-transform optimize model.glb model-final.glb \
--texture-compress basisu \
--meshopt \
--simplify --simplify-ratio 0.5 \
--weld --prune
Эта одна команда = чистка + сварка + MeshOpt для вершин + KTX2 для текстур + упрощение геометрии. Для 90% сценариев её достаточно; пошаговый подход нужен для понимания и настройки параметров.
Не хотите настраивать окружение? Онлайн-сжатие в Any3D
Описанные команды и скрипты gltf-transform требуют установки Node, настройки инструментов и запоминания параметров. Онлайн-инструмент сжатия Any3D избавляет от всего этого:
- Никаких скриптов и окружения — открыли страницу и работаете
- Модель не загружается на сервер — всё обрабатывается локально в браузере, файл не покидает ваше устройство
- Визуальная настройка — текстуры KTX2, вершины MeshOpt, упрощение геометрии: ползунки и предпросмотр в реальном времени
- Один клик — несколько версий — экспорт результатов под мобильные / десктоп / VR
Выбираете GLB, указываете целевую платформу, нажимаете кнопку — получаете сжатую модель. В основе тот же gltf-transform, что и в командной строке, но без порога входа и терминала.
FAQ: частые ошибки
После сжатия модель почернела / текстуры не отображаются
- В 99% случаев проблема в цветовом пространстве: для цветовых текстур забыли указать sRGB. В Three.js:
texture.colorSpace = THREE.SRGBColorSpace. - При использовании toktx для цветовых текстур забыли флаг
--srgb.
После сжатия карты нормалей освещение некорректное
- Карта нормалей сжата в ETC1S — переключите на UASTC.
- Карта нормалей в стиле DirectX (зелёный канал вниз), а движок ожидает OpenGL — нужно инвертировать G-канал.
На мобильных долгая загрузка первого экрана
- Проверьте, не загружается ли wasm-декодер Draco (лишний запрос). На мобильных предпочтителен MeshOpt.
- Неверно указан путь к транскодеру KTX2 — при сбое транскодирования происходит откат к распаковке на CPU.
После сжатия файл стал больше
- Текстуры слишком маленькие (< 128 px): сжатие в KTX2 невыгодно, у блокового сжатия есть фиксированные накладные расходы.
- Модель уже была сжата ранее — повторное сжатие не даёт выигрыша (или даёт отрицательный).
После упрощения геометрии появились артефакты
--simplify-ratioслишком низкий — поднимите до 0.7–0.8.- Упрощение хорошо работает для жёстких поверхностей (механика, архитектура), но плохо для органических форм (персонажи) — возможны разрывы.
KTX2 не загружается в некоторых браузерах
- Старые Safari / WebView не поддерживают. Подготовьте запасной вариант PNG/WebP или используйте поле
fallbackвKHR_texture_basisuдля запасных текстур.
Шпаргалка по всей серии
Квинтэссенция всех шести статей в одной таблице. Сохраните себе.
Структура объёма
| Компонент | Доля | Инструменты оптимизации |
|---|---|---|
| Текстуры | 70–85% | KTX2 (максимальный выигрыш) |
| Вершины | 10–20% | MeshOpt / квантование / Draco |
| Анимации | 0–15% | Сокращение ключевых кадров / сжатие |
| Прочее | < 2% | Чистка |
Формула видеопамяти
Память для обычных форматов = ширина * высота * 4 байта * 1.333 (с mipmap)
Память для KTX2 с блоковым сжатием ≈ предыдущее / 4 (