Текстуры формируют внешний вид большинства объектов в трёхмерной сцене. Поверхности моделей, отражения, освещение, нормали, шероховатость — всё это в Babylon.js реализуется с использованием текстурных данных, которые передаются в графический процессор. Количество, размер и формат этих текстур напрямую влияют на:
В WebGL-приложениях неоптимизированные текстуры часто становятся главным источником проблем производительности. Даже при простой геометрии сцена может потреблять сотни мегабайт видеопамяти, если используются слишком крупные или неправильно закодированные текстуры.
Babylon.js предоставляет широкий набор механизмов, позволяющих контролировать загрузку, хранение и использование текстур. Эффективная оптимизация достигается за счёт правильного выбора форматов, разумных размеров и объединения текстур в атласы.
Формат текстуры определяет способ хранения пикселей и степень их сжатия. От него зависят размер файла, объём видеопамяти и скорость передачи данных в GPU.
PNG — один из наиболее распространённых форматов текстур.
Особенности:
PNG подходит для текстур, где требуется точная передача деталей:
Пример загрузки PNG-текстуры:
const texture = new BABYLON.Texture("textures/diffuse.png", scene);
Недостатком PNG является отсутствие GPU-сжатия. После загрузки такая текстура распаковывается и занимает значительно больше видеопамяти, чем исходный файл.
JPEG используется для текстур без прозрачности.
Преимущества:
Недостатки:
Типичные области применения:
Пример:
const texture = new BABYLON.Texture("textures/terrain.jpg", scene);
WebP сочетает преимущества PNG и JPEG.
Особенности:
WebP часто используется для веб-приложений, где важна скорость загрузки.
Наиболее эффективными считаются форматы, которые хранятся в сжатом виде непосредственно в видеопамяти. Они уменьшают потребление VRAM и ускоряют рендеринг.
Основные форматы:
| Формат | Платформы |
|---|---|
| DXT / S3TC | Desktop |
| ETC1 / ETC2 | Android |
| PVRTC | iOS |
| ASTC | Современные GPU |
Babylon.js поддерживает их через контейнеры:
Пример загрузки KTX2:
const texture = new BABYLON.Texture("textures/diffuse.ktx2", scene);
GPU-сжатые текстуры:
Формат Basis Universal стал стандартом оптимизации текстур в WebGL.
Особенности:
Контейнер 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.
WebGL исторически оптимизирован для текстур со сторонами, равными степеням двойки:
Такие текстуры:
Babylon.js автоматически работает и с произвольными размерами, но использование степеней двойки остаётся лучшей практикой.
Максимальный размер текстуры зависит от видеокарты. Получить его можно через движок:
const maxSize = engine.getCaps().maxTextureSize;
Типичные значения:
| Устройство | Максимум |
|---|---|
| мобильные | 2048–4096 |
| ноутбуки | 4096–8192 |
| мощные GPU | 16384 |
Использование текстур, превышающих возможности устройства, приводит к ошибкам или автоматическому уменьшению.
Часто исходные текстуры создаются слишком большими. Это приводит к перерасходу памяти.
Оптимизация включает:
Пример:
| Объект | Рекомендуемый размер |
|---|---|
| мелкие детали | 256×256 |
| стандартные объекты | 512×512 |
| крупные модели | 1024×1024 |
| главный объект сцены | 2048×2048 |
Использование текстуры 4K для маленького объекта является неэффективным.
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|
+----------------------+
Каждый объект использует только часть атласа.
Использование атласов уменьшает количество:
GPU работает быстрее, когда множество объектов используют одну и ту же текстуру.
В WebGL переключение текстуры — дорогая операция. Атласы значительно снижают этот overhead.
Для работы с атласами используется настройка UV-координат.
UV определяют, какая часть текстуры применяется к поверхности.
Пример диапазона:
U: 0.25 – 0.5
V: 0.0 – 0.25
Это означает использование определённого фрагмента атласа.
В Babylon.js UV-координаты задаются в геометрии меша.
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 выбирает нужный кадр внутри атласа.
Интерфейсные элементы также часто объединяются в один атлас:
Это уменьшает количество сетевых запросов и ускоряет загрузку интерфейса.
Создание атласов выполняется специальными инструментами:
Процесс включает:
Часто дополнительно создаётся JSON-файл с координатами фрагментов.
При создании атласов возникают артефакты на границах изображений.
Причина — фильтрация текстур.
Для решения используется padding — добавление отступов между элементами.
Типичный размер:
2–4 пикселя
Это предотвращает «подтекание» соседних пикселей.
В крупных проектах используется несколько атласов:
Это балансирует между:
Огромный атлас 8K может быть хуже нескольких 2K атласов.
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.
Оптимизация текстур обычно выполняется в следующем порядке:
Такая последовательность позволяет значительно снизить нагрузку на GPU и улучшить частоту кадров даже в сложных WebGL-сценах.