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

Three.js предоставляет богатые возможности для работы с текстурами, обеспечивая поддержку различных форматов и методов сжатия, что критически важно для производительности веб-приложений. Понимание того, какой формат использовать и как эффективно применять сжатие, позволяет значительно снизить нагрузку на графический процессор и ускорить загрузку сцены.


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

Three.js поддерживает несколько категорий форматов:

  1. Растровые изображения (Bitmap)

    • JPEG – эффективен для фотографий и изображений с плавными переходами цвета. Отличается высокой степенью сжатия, но теряет информацию (lossy). Не поддерживает прозрачность.
    • PNG – поддерживает прозрачность (альфа-канал), идеально подходит для спрайтов и UI-элементов. Сжатие без потерь (lossless), поэтому размер файлов больше, чем у JPEG.
    • GIF – поддерживает анимацию и прозрачность, но ограничен 256 цветами. Практически не используется для 3D-текстур в Three.js из-за низкого качества.
  2. Высокодинамические изображения (HDR и EXR)

    • HDR (.hdr) – используется для освещения через environment maps. Позволяет хранить значения освещенности вне диапазона [0,1], что важно для PBR (Physically Based Rendering).
    • EXR (.exr) – аналог HDR, поддерживает 16- или 32-битные форматы с плавающей точкой. Используется в сценах с высокодинамическим освещением и постобработкой.
  3. Форматы сжатия для WebGL WebGL поддерживает специализированные форматы сжатых текстур, которые загружаются напрямую в видеопамять, минуя CPU. Three.js предоставляет загрузчики для таких форматов:

    • DDS (S3TC / DXT) – старый формат для Windows/DirectX, поддерживает блоковое сжатие и Mipmap. Подходит для игр с большим количеством текстур.
    • KTX / KTX2 (Basis Universal) – современный формат, поддерживающий конвертацию в GPU-native форматы на лету. KTX2 с Basis Universal значительно уменьшает размер текстур без заметной потери качества.
    • PVR (PVRTC) – эффективен для устройств Apple, поддерживает сжатие с потерями и быстрый рендеринг на iOS.

Сжатие текстур

Сжатие текстур критически важно для оптимизации производительности. Различают несколько методов:

  1. Сжатие с потерями (Lossy)

    • Уменьшает размер файлов за счёт потери точности цвета.
    • Примеры: JPEG, Basis Universal, PVRTC.
    • Используется для больших карт диффузного цвета, где небольшие артефакты малозаметны.
  2. Сжатие без потерь (Lossless)

    • Сохраняет исходное качество пикселей.
    • Примеры: PNG, EXR.
    • Не всегда эффективен для игр из-за больших размеров, но полезен для карт нормалей и альфа-каналов.
  3. Блоковое сжатие (Block Compression)

    • Текстура делится на блоки, каждый из которых сжимается независимо.
    • Примеры: DXT1/5, ETC1/2, ASTC.
    • Позволяет GPU декодировать данные без участия CPU, обеспечивая мгновенную загрузку и рендеринг.

Работа с форматами в Three.js

Three.js предоставляет удобные загрузчики для всех популярных форматов:

  • THREE.TextureLoader – для PNG, JPEG, GIF. Позволяет загружать растровые изображения и автоматически создавать Mipmap.
  • THREE.RGBELoader – для HDR-текстур, применяемых в environment maps.
  • THREE.EXRLoader – для EXR-файлов с высокодинамическим диапазоном.
  • THREE.KTX2Loader – для KTX2/Basis Universal. Поддерживает конвертацию текстур в GPU-native формат через Basis Universal transcoder.
  • THREE.DDSLoader / PVRLoader – для платформенно-специфичных сжатых форматов.

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

const ktx2Loader = new THREE.KTX2Loader()
  .setTranscoderPath('js/libs/basis/')
  .detectSupport(renderer);

ktx2Loader.load('textures/texture.ktx2', (texture) => {
  texture.encoding = THREE.sRGBEncoding;
  texture.wrapS = THREE.RepeatWrapping;
  texture.wrapT = THREE.RepeatWrapping;
  material.map = texture;
  material.needsUpdate = true;
});

Mipmap и фильтрация

Использование Mipmap в сжатых текстурах позволяет уменьшить артефакты при уменьшении размера текстуры на экране. Three.js автоматически генерирует Mipmap при загрузке большинства форматов, но для сжатых текстур KTX2 и DDS Mipmap может быть закодирован заранее.

Фильтрация текстур управляется свойствами:

  • texture.minFilter – фильтр при уменьшении (например, THREE.LinearMipmapLinearFilter).
  • texture.magFilter – фильтр при увеличении (например, THREE.LinearFilter).
  • texture.wrapS / wrapT – режимы повторения или отражения текстуры (THREE.RepeatWrapping, THREE.MirroredRepeatWrapping).

Эффективная комбинация Mipmap и фильтров позволяет получить плавное отображение текстур с минимальными артефактами и нагрузкой на GPU.


Выбор формата по типу карты

  • Diffuse / Albedo – KTX2/Basis или JPEG для быстрого рендеринга.
  • Normal / Bump – PNG или сжатие без потерь для точности нормалей.
  • Specular / Roughness / Metalness – KTX2/Basis, часто объединяют в каналы одного изображения (packed maps).
  • Environment / Skybox – HDR или EXR для корректного освещения сцены.

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

  • Минимизация количества текстур через texture atlases.
  • Использование Basis Universal для уменьшения веса и кроссплатформенной совместимости.
  • Загрузка текстур асинхронно с отображением placeholder-материалов.
  • Генерация Mipmap заранее для сжатых текстур, чтобы избежать затрат GPU при первом рендеринге.

Эффективное управление форматами и сжатием текстур позволяет Three.js обеспечивать высокую производительность даже в сложных сценах с большим количеством материалов и освещения.