Оптимизация текстур: форматы, размеры, атласы

Текстуры формируют внешний вид большинства объектов в трёхмерной сцене. Поверхности моделей, отражения, освещение, нормали, шероховатость — всё это в Babylon.js реализуется с использованием текстурных данных, которые передаются в графический процессор. Количество, размер и формат этих текстур напрямую влияют на:

  • использование видеопамяти;
  • скорость загрузки сцены;
  • частоту кадров;
  • нагрузку на GPU и CPU.

В WebGL-приложениях неоптимизированные текстуры часто становятся главным источником проблем производительности. Даже при простой геометрии сцена может потреблять сотни мегабайт видеопамяти, если используются слишком крупные или неправильно закодированные текстуры.

Babylon.js предоставляет широкий набор механизмов, позволяющих контролировать загрузку, хранение и использование текстур. Эффективная оптимизация достигается за счёт правильного выбора форматов, разумных размеров и объединения текстур в атласы.


Форматы текстур

Формат текстуры определяет способ хранения пикселей и степень их сжатия. От него зависят размер файла, объём видеопамяти и скорость передачи данных в GPU.

PNG

PNG — один из наиболее распространённых форматов текстур.

Особенности:

  • без потерь качества;
  • поддержка альфа-канала;
  • высокий уровень совместимости;
  • относительно большой размер файла.

PNG подходит для текстур, где требуется точная передача деталей:

  • пользовательские интерфейсы;
  • текст;
  • карты нормалей;
  • маски прозрачности.

Пример загрузки PNG-текстуры:

const texture = new BABYLON.Texture("textures/diffuse.png", scene);

Недостатком PNG является отсутствие GPU-сжатия. После загрузки такая текстура распаковывается и занимает значительно больше видеопамяти, чем исходный файл.


JPEG

JPEG используется для текстур без прозрачности.

Преимущества:

  • значительно меньший размер файла;
  • быстрая загрузка по сети.

Недостатки:

  • потери качества;
  • отсутствие альфа-канала;
  • появление артефактов при сильном сжатии.

Типичные области применения:

  • текстуры ландшафтов;
  • фотографии;
  • фоновые изображения;
  • большие диффузные карты.

Пример:

const texture = new BABYLON.Texture("textures/terrain.jpg", scene);

WebP

WebP сочетает преимущества PNG и JPEG.

Особенности:

  • поддержка прозрачности;
  • высокое сжатие;
  • меньший размер по сравнению с PNG;
  • хорошая поддержка современными браузерами.

WebP часто используется для веб-приложений, где важна скорость загрузки.


GPU-сжатые форматы

Наиболее эффективными считаются форматы, которые хранятся в сжатом виде непосредственно в видеопамяти. Они уменьшают потребление VRAM и ускоряют рендеринг.

Основные форматы:

Формат Платформы
DXT / S3TC Desktop
ETC1 / ETC2 Android
PVRTC iOS
ASTC Современные GPU

Babylon.js поддерживает их через контейнеры:

  • KTX
  • DDS
  • Basis / KTX2

Пример загрузки KTX2:

const texture = new BABYLON.Texture("textures/diffuse.ktx2", scene);

GPU-сжатые текстуры:

  • занимают в 4–8 раз меньше видеопамяти;
  • быстрее передаются в GPU;
  • уменьшают время загрузки сцены.

Basis и KTX2

Формат Basis Universal стал стандартом оптимизации текстур в WebGL.

Особенности:

  • универсальное сжатие;
  • автоматическое преобразование под GPU устройства;
  • компактные размеры файлов.

Контейнер KTX2 позволяет хранить текстуры Basis и автоматически перекодировать их в нужный GPU-формат во время загрузки.

Babylon.js поддерживает KTX2 через встроенный транслятор.

Преимущества:

  • минимальный размер загрузки;
  • оптимальное использование видеопамяти;
  • высокая совместимость между устройствами.

Размеры текстур

Размер текстуры оказывает критическое влияние на производительность.

Видеопамять, используемая текстурой, зависит от количества пикселей:

память = ширина × высота × количество каналов

Например:

Размер Пикселей Примерный объём
512×512 262 144 ~1 MB
1024×1024 1 048 576 ~4 MB
2048×2048 4 194 304 ~16 MB
4096×4096 16 777 216 ~64 MB

Одна текстура 4K может занимать десятки мегабайт VRAM.


Степени двойки (Power of Two)

WebGL исторически оптимизирован для текстур со сторонами, равными степеням двойки:

  • 128
  • 256
  • 512
  • 1024
  • 2048
  • 4096

Такие текстуры:

  • поддерживают mip-карты;
  • быстрее обрабатываются GPU;
  • лучше кэшируются.

Babylon.js автоматически работает и с произвольными размерами, но использование степеней двойки остаётся лучшей практикой.


Ограничения GPU

Максимальный размер текстуры зависит от видеокарты. Получить его можно через движок:

const maxSize = engine.getCaps().maxTextureSize;

Типичные значения:

Устройство Максимум
мобильные 2048–4096
ноутбуки 4096–8192
мощные GPU 16384

Использование текстур, превышающих возможности устройства, приводит к ошибкам или автоматическому уменьшению.


Уменьшение размеров текстур

Часто исходные текстуры создаются слишком большими. Это приводит к перерасходу памяти.

Оптимизация включает:

  • уменьшение разрешения;
  • использование mip-карт;
  • масштабирование под реальные размеры объектов.

Пример:

Объект Рекомендуемый размер
мелкие детали 256×256
стандартные объекты 512×512
крупные модели 1024×1024
главный объект сцены 2048×2048

Использование текстуры 4K для маленького объекта является неэффективным.


Mip-карты

Mip-карты — это набор уменьшенных копий текстуры.

Пример уровней:

1024x1024
512x512
256x256
128x128
64x64
...

GPU автоматически выбирает подходящий уровень в зависимости от расстояния до камеры.

Преимущества:

  • уменьшение мерцания текстур;
  • повышение производительности;
  • экономия пропускной способности памяти.

Babylon.js создаёт mip-карты автоматически:

const texture = new BABYLON.Texture("texture.jpg", scene, true);

Третий параметр включает генерацию mip-карт.


Фильтрация текстур

Фильтрация определяет способ интерполяции пикселей при масштабировании.

Основные режимы:

Режим Назначение
NEAREST быстрый, пиксельный
BILINEAR сглаживание
TRILINEAR плавные переходы mip-карт

В Babylon.js:

texture.updateSamplingMode(BABYLON.Texture.TRILINEAR_SAMPLINGMODE);

Trilinear фильтрация обеспечивает лучший визуальный результат, но требует немного больше ресурсов.


Атласы текстур

Текстурный атлас — это большая текстура, содержащая множество маленьких изображений.

Пример:

+----------------------+
| icon1 | icon2 | icon3|
| icon4 | icon5 | icon6|
+----------------------+

Каждый объект использует только часть атласа.


Преимущества атласов

Использование атласов уменьшает количество:

  • переключений текстур;
  • draw-call;
  • загрузок ресурсов.

GPU работает быстрее, когда множество объектов используют одну и ту же текстуру.

В WebGL переключение текстуры — дорогая операция. Атласы значительно снижают этот overhead.


Координаты UV

Для работы с атласами используется настройка UV-координат.

UV определяют, какая часть текстуры применяется к поверхности.

Пример диапазона:

U: 0.25 – 0.5
V: 0.0 – 0.25

Это означает использование определённого фрагмента атласа.

В Babylon.js UV-координаты задаются в геометрии меша.


Использование атласа в Babylon.js

const texture = new BABYLON.Texture("atlas.png", scene);

material.diffuseTexture = texture;

При этом UV-координаты модели определяют участок текстуры.


Атласы для спрайтов

Babylon.js активно использует текстурные атласы для систем спрайтов.

Создание менеджера:

const spriteManager = new BABYLON.SpriteManager(
    "sprites",
    "spritesheet.png",
    100,
    64,
    scene
);

Параметры:

  • имя менеджера;
  • путь к атласу;
  • максимальное число спрайтов;
  • размер одного кадра.

После этого можно создавать спрайты:

const sprite = new BABYLON.Sprite("player", spriteManager);
sprite.cellIndex = 3;

cellIndex выбирает нужный кадр внутри атласа.


Атласы для UI

Интерфейсные элементы также часто объединяются в один атлас:

  • кнопки;
  • иконки;
  • панели;
  • индикаторы.

Это уменьшает количество сетевых запросов и ускоряет загрузку интерфейса.


Packing текстур

Создание атласов выполняется специальными инструментами:

  • TexturePacker
  • Free Texture Packer
  • Blender UV packing
  • встроенные средства игровых движков

Процесс включает:

  1. размещение изображений;
  2. минимизацию пустого пространства;
  3. генерацию координат.

Часто дополнительно создаётся JSON-файл с координатами фрагментов.


Padding и bleeding

При создании атласов возникают артефакты на границах изображений.

Причина — фильтрация текстур.

Для решения используется padding — добавление отступов между элементами.

Типичный размер:

2–4 пикселя

Это предотвращает «подтекание» соседних пикселей.


Многоуровневые атласы

В крупных проектах используется несколько атласов:

  • атлас окружения;
  • атлас персонажей;
  • атлас интерфейса.

Это балансирует между:

  • количеством draw-call;
  • размером текстур.

Огромный атлас 8K может быть хуже нескольких 2K атласов.


Lazy-загрузка текстур

Babylon.js позволяет загружать текстуры только при необходимости.

Это уменьшает стартовое время сцены.

Пример:

const texture = new BABYLON.Texture(
    "texture.jpg",
    scene,
    false,
    false,
    BABYLON.Texture.TRILINEAR_SAMPLINGMODE,
    () => {
        console.log("Texture loaded");
    }
);

Повторное использование текстур

Одна текстура может применяться к множеству материалов.

Babylon.js автоматически кэширует текстуры:

material1.diffuseTexture = texture;
material2.diffuseTexture = texture;

Это предотвращает повторную загрузку и экономит память.


Оптимизация памяти текстур

Основные правила:

1. Минимизировать разрешение. Текстура должна соответствовать размеру объекта на экране.

2. Использовать GPU-сжатие. KTX2 и Basis значительно уменьшают VRAM.

3. Объединять текстуры в атласы.

4. Избегать лишних карт. Если объекту не требуется normal или roughness карта, её лучше удалить.

5. Повторно использовать ресурсы.


Инструменты анализа

Babylon.js предоставляет инструменты для анализа сцены.

Inspector:

scene.debugLayer.show();

В разделе Textures отображаются:

  • размеры текстур;
  • формат;
  • использование памяти.

Это позволяет быстро обнаружить неоптимизированные ресурсы.


Типичные ошибки оптимизации

Использование слишком больших текстур

Частая ситуация — загрузка 4K текстур для небольших объектов.

Отсутствие сжатия

PNG и JPEG после загрузки занимают много видеопамяти.

Чрезмерное количество материалов

Каждый материал может использовать отдельную текстуру, увеличивая draw-calls.

Отсутствие атласов

Множество маленьких текстур создаёт лишние переключения GPU.


Практическая стратегия оптимизации

Оптимизация текстур обычно выполняется в следующем порядке:

  1. анализ использования памяти;
  2. уменьшение разрешения текстур;
  3. переход на KTX2 / Basis;
  4. объединение текстур в атласы;
  5. проверка mip-карт и фильтрации;
  6. повторный анализ производительности.

Такая последовательность позволяет значительно снизить нагрузку на GPU и улучшить частоту кадров даже в сложных WebGL-сценах.