Texture atlasing — техника объединения нескольких текстур в один большой спрайтовый атлас. Основная цель — снижение количества вызовов рендеринга (draw calls) и оптимизация производительности WebGL-приложений. В Three.js она особенно актуальна при работе с большим количеством объектов, использующих одни и те же материалы с разными текстурами.
Атласирование строится на нескольких ключевых моментах:
Объединение текстур Несколько маленьких изображений (например, 256×256 px) объединяются в один большой атлас (например, 2048×2048 px). Это позволяет GPU выполнять меньше переключений текстур во время рендеринга сцены.
UV-координаты При использовании атласа
необходимо корректировать UV-координаты каждого объекта. В
UV-пространстве [0, 1] каждая часть атласа соответствует
отдельной текстуре. Если объект использует только часть атласа, UV нужно
масштабировать и сдвигать так, чтобы они указывали на нужный
регион.
Форматы и фильтрация Атлас должен быть в формате, поддерживаемом GPU (например, PNG или JPEG). Следует учитывать фильтрацию: линейная фильтрация может привести к смешиванию цветов по краям отдельных текстур. Для предотвращения артефактов применяют padding — небольшие пустые границы между изображениями внутри атласа.
Three.js не предоставляет встроенных инструментов для генерации атласов на лету, поэтому обычно используют сторонние библиотеки или генерацию атласа на этапе сборки проекта.
Пример ручного создания атласа:
import * as THREE from 'three';
// Загружаем отдельные текстуры
const loader = new THREE.TextureLoader();
const tex1 = loader.load('image1.png');
const tex2 = loader.load('image2.png');
// Создаём канвас для атласа
const canvas = document.createElement('canvas');
canvas.width = 512;
canvas.height = 256;
const ctx = canvas.getContext('2d');
// Рисуем текстуры в канвас
ctx.drawImage(tex1.image, 0, 0);
ctx.drawImage(tex2.image, 256, 0);
// Создаём текстуру Three.js из канваса
const atlasTexture = new THREE.CanvasTexture(canvas);
// Применяем к материалу
const material = new THREE.MeshBasicMaterial({ map: atlasTexture });
После этого необходимо корректировать UV-координаты. Например, если первая текстура занимает левую половину атласа:
geometry.faceVertexUvs[0].forEach(uvs => {
uvs.forEach(uv => {
uv.x *= 0.5; // сжатие по горизонтали
});
});
geometry.uvsNeedUpdate = true;
Для второй текстуры сдвиг по X будет равен 0.5, а масштаб 0.5.
Для крупных проектов удобно использовать генераторы атласов, такие как:
Three.js позволяет легко интегрировать JSON-данные, содержащие
координаты спрайтов, с помощью THREE.Texture и
THREE.Mesh.
Texture atlasing особенно эффективен для спрайт-анимаций. Один атлас может содержать все кадры анимации персонажа, что позволяет анимировать объект, меняя UV-координаты вместо загрузки новых текстур.
Пример циклической анимации:
const frames = [
{ x: 0, y: 0, w: 0.25, h: 1 }, // кадр 1
{ x: 0.25, y: 0, w: 0.25, h: 1 }, // кадр 2
// ...
];
let currentFrame = 0;
function animate() {
requestAnimationFrame(animate);
const frame = frames[currentFrame];
geometry.faceVertexUvs[0].forEach(uvs => {
uvs.forEach(uv => {
uv.x = uv.x * frame.w + frame.x;
uv.y = uv.y * frame.h + frame.y;
});
});
geometry.uvsNeedUpdate = true;
currentFrame = (currentFrame + 1) % frames.length;
renderer.render(scene, camera);
}
animate();
Texture atlasing позволяет значительно улучшить производительность Three.js-приложений при работе с множеством объектов и анимаций. Корректная работа с UV и продуманная структура атласов делают сцену более лёгкой для GPU и обеспечивают плавный рендеринг даже на слабых устройствах.