TextureLoader и загрузка изображений

TextureLoader — это основной инструмент для загрузки изображений и использования их в качестве текстур на объектах сцены. Работа с текстурами включает несколько ключевых этапов: инициализация загрузчика, асинхронная загрузка изображения, обработка загруженной текстуры и её применение к материалу.

import * as THREE from 'three';

const loader = new THREE.TextureLoader();
loader.load(
    'textures/wood.jpg',
    function(texture) {
        const material = new THREE.MeshBasicMaterial({ map: texture });
        const geometry = new THREE.BoxGeometry(1, 1, 1);
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
    },
    undefined,
    function(err) {
        console.error('Ошибка загрузки текстуры:', err);
    }
);

Основные методы и параметры

Метод load принимает четыре аргумента:

  1. URL текстуры — путь к изображению.
  2. onLoad — функция обратного вызова, выполняемая после успешной загрузки текстуры.
  3. onProgress — функция обратного вызова для отслеживания прогресса загрузки (не всегда поддерживается во всех браузерах).
  4. onError — функция, вызываемая при ошибке загрузки.

Асинхронная загрузка с помощью Promise

Для современных приложений удобно использовать Promise для обработки текстур:

function loadTexture(url) {
    return new Promise((resolve, reject) => {
        const loader = new THREE.TextureLoader();
        loader.load(
            url,
            texture => resolve(texture),
            undefined,
            err => reject(err)
        );
    });
}

loadTexture('textures/metal.jpg')
    .then(texture => {
        const material = new THREE.MeshStandardMaterial({ map: texture });
        const geometry = new THREE.SphereGeometry(0.5, 32, 32);
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
    })
    .catch(err => console.error(err));

Использование async/await делает код ещё более читаемым:

async function init() {
    const texture = await loadTexture('textures/marble.jpg');
    const material = new THREE.MeshStandardMaterial({ map: texture });
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
}
init();

Свойства текстур

После загрузки текстуры она обладает рядом важных свойств:

  • wrapS и wrapT — режимы повторения по осям U и V (THREE.RepeatWrapping, THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping).
  • repeat — вектор THREE.Vector2, задающий количество повторов текстуры.
  • offset — смещение текстуры по координатам U и V.
  • rotation — вращение текстуры вокруг центра.
  • flipY — флаг, определяющий переворот текстуры по вертикали (по умолчанию true).

Пример применения свойств:

const texture = await loadTexture('textures/fabric.jpg');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(4, 4);
texture.rotation = Math.PI / 4;

const material = new THREE.MeshStandardMaterial({ map: texture });

Работа с форматом изображений

Three.js поддерживает большинство стандартных форматов: jpg, png, gif. Для прозрачных текстур используется png с альфа-каналом. При загрузке текстур с прозрачностью необходимо включать альфа-канал в материале:

const material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true
});

Производительность и оптимизация

  • Для уменьшения нагрузки рекомендуется использовать текстуры меньшего разрешения.
  • Настройка minFilter и magFilter влияет на качество и производительность:
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.magFilter = THREE.LinearFilter;
  • Для больших сцен можно использовать TextureLoader вместе с LoadingManager для отслеживания загрузки нескольких текстур:
const manager = new THREE.LoadingManager();
manager.onSt art = () => console.log('Начало загрузки');
manager.onL oad = () => console.log('Все текстуры загружены');
manager.onEr ror = url => console.error('Ошибка при загрузке', url);

const loader = new THREE.TextureLoader(manager);
const texture1 = loader.load('textures/wood.jpg');
const texture2 = loader.load('textures/metal.jpg');

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

Для сложных материалов можно комбинировать несколько текстур, например: карта цвета (map), нормали (normalMap), металлические отражения (metalnessMap) и т.д. Это позволяет создавать реалистичные поверхности:

const material = new THREE.MeshStandardMaterial({
    map: await loadTexture('textures/wood_diffuse.jpg'),
    normalMap: await loadTexture('textures/wood_normal.jpg'),
    roughnessMap: await loadTexture('textures/wood_roughness.jpg')
});

Эта стратегия широко применяется в PBR-рендеринге, позволяя добиться высокой реалистичности с минимальными затратами ресурсов.

Итоговые рекомендации

  • Использовать async/await или Promise для асинхронной загрузки текстур.
  • Настраивать wrap, repeat, rotation и flipY для точного отображения изображения.
  • Применять LoadingManager при работе с множеством текстур.
  • Оптимизировать разрешение и фильтры текстур для повышения производительности сцены.

Такая структура загрузки и управления текстурами позволяет создавать сложные и визуально богатые 3D-сцены в Three.js, минимизируя ошибки и задержки при рендеринге.