1. Главная
  2. Блог
  3. 3D на сайте / WebGL

Скорость 3D-сайта: glTF, Draco, KTX2 и версии для смартфонов

Лимиты, сжатие и порядок загрузки, с которыми интерактивное 3D быстро работает на смартфоне среднего класса.

ASFARI digital5 мин чтенияОктябрь 2026

Детализированная хромированная скульптура и её упрощённая низкополигональная версия, рядом измерительные ленты

Чтобы 3D-сайт работал быстро, нужны три решения. Ещё до моделирования задайте жёсткие лимиты по числу треугольников, размеру файлов и вызовам отрисовки. Сожмите все материалы: геометрию с помощью Draco или meshopt, текстуры с помощью KTX2. Загружайте 3D только после первого отображения HTML-страницы, а для слабых телефонов предусмотрите статичное изображение или видео. Тогда 3D в реальном времени может укладываться в хорошие показатели Google Core Web Vitals.

Рассказываем, как мы делаем это в ASFARI digital.

Сначала задайте ограничения для 3D

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

Параметр Рабочий ориентир ASFARI digital
Треугольники в сцене первого экрана на смартфоне ≤ 100 000
Модель первого экрана, сжатый GLB ≤ 2 МБ
Текстуры 1K-2K, KTX2
Вызовы отрисовки ≤ 50
Готовность к первому действию на смартфоне среднего класса Менее 3 с
3D-модуль Загружается после первого отображения страницы
Таблица рабочих ограничений ASFARI digital для мобильной 3D-сцены: число треугольников, размер GLB и текстур, вызовы отрисовки и время до первого возможного действия
Наши рабочие ограничения для сцены на первом экране мобильного сайта. На компьютере можно позволить больше, но верхнюю планку задаёт смартфон.

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

Сжатие glTF: Draco, meshopt и KTX2

glTF - стандартный формат 3D для веба (Khronos). Файлы после экспорта бывают большими, но сжатие часто существенно уменьшает их размер.

  • Draco сжимает геометрию сетки. Хорошо подходит для плотных сеток, но требует немного времени на декодирование.
  • meshopt - другой способ сжатия геометрии с очень быстрым декодированием. Стоит сравнить его с Draco на вашей модели.
  • KTX2 / Basis Universal сжимает текстуры в формат, с которым графический процессор работает напрямую. JPG или PNG могут мало весить при загрузке, но в памяти GPU разворачиваются до полного размера. KTX2 остаётся сжатым и там, что помогает избежать сбоев на телефонах.

С открытым инструментом командной строки glTF-Transform первая обработка выглядит так (команды из документации):

npm install --global @gltf-transform/cli
gltf-transform inspect hero.glb        # треугольники, текстуры, размеры
gltf-transform optimize hero.glb hero-opt.glb --compress draco --texture-compress webp

Для KTX2 используйте соответствующие команды обработки текстур вместо WebP. Для них потребуется установленный KTX-Software. Затем настройте декодирование обоих форматов в Three.js:

const draco = new DRACOLoader().setDecoderPath('/draco/');
const ktx2 = new KTX2Loader().setTranscoderPath('/basis/').detectSupport(renderer);
const loader = new GLTFLoader().setDRACOLoader(draco).setKTX2Loader(ktx2);

Запустите inspect до и после обработки. Всё ещё выходите за лимиты? Скорее всего, нужно доработать модель в Blender, а не сильнее сжимать файл.

Загружайте 3D после первого отображения страницы

Библиотека 3D вместе с моделями может занимать много места. По данным Utsubo, минифицированное ядро Three.js весит около 600 КБ, а с вспомогательными модулями, постобработкой и GLB - более 3 МБ. Если всё это блокирует загрузку страницы, ухудшается показатель Largest Contentful Paint.

Схема загрузки 3D: сначала HTML и статичное изображение, после первого отображения страницы загружается 3D-модуль, затем плавно появляется интерактивная сцена
Порядок загрузки: сначала HTML и статичное изображение, затем код 3D и в конце интерактивность.

Порядок действий:

  1. Сформируйте HTML на сервере, включая заголовок и призыв к действию.
  2. Покажите статичное изображение в блоке с фиксированным соотношением сторон, чтобы появление canvas не сдвигало содержимое.
  3. Импортируйте код 3D, когда браузер не занят другими задачами или пользователь прокрутит до нужного блока.
  4. Когда первый кадр готов, плавно замените статичное изображение на canvas.
const start = () => import('./hero-scene.js').then(m => m.mount(canvas));
'requestIdleCallback' in window ? requestIdleCallback(start) : setTimeout(start, 200);

Так же устроен глобус на главной странице GitHub. Пока первый кадр не готов, видна SVG-заглушка. Затем она плавно сменяется canvas за 600 мс. Этот подход важен и для поиска; подробнее в статье «SEO для WebGL-сайтов».

Скорость WebGL на смартфонах: режимы для разных устройств

Не нужно показывать одну и ту же сцену на всех телефонах. Предусмотрите как минимум три режима:

  • Высокое качество: полная сцена, коэффициент плотности пикселей ограничен значением 2 (renderer.setPixelRatio(Math.min(devicePixelRatio, 2))).
  • Низкое качество: меньше частиц, без постобработки, коэффициент плотности пикселей 1-1,5.
  • Запасной вариант: заранее отрендеренное зацикленное видео или статичное изображение. Видео без звука с атрибутом playsinline может автоматически воспроизводиться внутри страницы на iOS.

Адаптируйте качество и во время работы. Глобус GitHub отслеживает частоту кадров и снижает качество, если не удерживает 55,5 FPS за последние 50 кадров. Он последовательно проходит четыре уровня качества: снижает плотность пикселей, реже проверяет пересечения лучей и уменьшает число точек примерно на треть.

Чтобы оптимизировать Three.js во время разработки, записывайте значения renderer.info.render.calls и renderer.info.render.triangles для каждого кадра и сравнивайте с лимитами. Учитывайте настройку prefers-reduced-motion: пользователю, который выбрал уменьшение движения, показывайте статичное изображение вместо вращающейся сцены.

Проверяйте показатели Core Web Vitals

Google считает хорошими показатели LCP ≤ 2,5 с, INP ≤ 200 мс и CLS ≤ 0,1. На странице с 3D самым крупным элементом для LCP часто становится canvas или статичное изображение. Долгая компиляция шейдеров ухудшает INP.

Пороговые значения Core Web Vitals для LCP, INP и CLS: хорошие показатели, требующие улучшения и плохие
Пороговые значения Google Core Web Vitals. Проверяйте на настоящем смартфоне среднего класса; одного запуска Lighthouse на компьютере недостаточно.

По оценке Utsubo, компиляция одного шейдера занимает 50-300 мс, а декодирование крупной текстуры - 50-200 мс. Поэтому подготавливайте шейдеры до первого действия пользователя. Общие вопросы анимации разбираем в статье «Замедляет ли анимация сайт?». Если нужна отдельная модель товара, а не целая сцена, читайте «Как добавить интерактивную 3D-модель на сайт».

Частые вопросы

Источники

НОВЫЙ ПРОЕКТ

Расскажите
о задаче

Что нужно?

Заявку получим на hello@asfari.digital. Ответим в течение 24 часов.

    Подробнее об услуге ПРИМЕР ПРОЕКТА