Сжатие текстур, часть V. ASTC и Basis Universal

Продолжение серии постов о сжатых текстурных форматах. Предыдущие части: часть I, часть II, часть III, часть IV.

Вот мы и подошли к state of the art текстурного сжатия по состоянию на 2025 год.

ASTC

Adaptive Scalable Texture Compression

Современный формат, созданный с учетом особенностей мобильных платформ. На сегодняшний день крайне мало распространен. Программно поддерживается в Vulkan и новейших версиях OpenGL ES, но аппаратно — далеко не всеми видеокартами. В десктопном OpenGL поддержки нет и, судя по всему, не предвидится (но это не проблема — см. ниже).

В отличие от S3TC, BPTC и RGTC, формат работает с блоками от 4×4 до 12×12. Размер блока ASTC всегда составляет 16 байт, поэтому чем больше блок, тем выше степень сжатия, но ниже качество. Можно выбирать формат блока (например, 5×5, 6×6, 8×8 и т.д.) в зависимости от баланса между качеством и размером. ASTC поддерживает от 1 до 4 каналов.

ASTC поддерживает HDR и является на сегодняшний день единственным универсальным решением для сжатия HDR-текстур на мобильных GPU.

Basis Universal

Использовать ASTC напрямую непрактично, если вы хотите охватить широкий спектр платформ и конфигураций. Для этого была придумана особая система хранения сжатых текстур, которая позволяет приложениям на лету транскодировать их в формат, подходящий для каждой конкретной платформы — ASTC, BPTC, S3TC, RGTC, PVRTC и в несжатые форматы. Basis Universal охватывает как LDR, так и HDR-текстуры в рамках пяти режимов сжатия: ETC1S, UASTC LDR 4×4, UASTC HDR 4×4, UASTC HDR 6×6, UASTC HDR 6×6 intermediate.

ETC1S. Режим низкого и среднего качества, основанный на подмножестве ETC1. Поддерживает переменный баланс веса/качества (наподобие JPEG). Поддерживает альфа-канал. Этот вид текстур можно быстро транскодировать практически в любые другие сжатые форматы.

UASTC (Universal ASTC) LDR 4×4. Подмножество ASTC для стандартных LDR-текстур с 8 битами на канал. Транскодируется также очень эффективно, особенно в ASTC и BC7.

UASTC HDR 4×4. Режим для HDR-текстур, подмножество ASTC HDR 4×4 8bpp. Разработан для обеспечения высокого качества, эффективно транскодируется (с небольшими потерями) в BC6H. В ASTC HDR превращается вообще без какого-либо оверхеда и без потерь. Этот режим также можно транскодировать в различные несжатые HDR-форматы 32-64 bpp.

UASTC HDR 6×6. Режим HDR-текстур 3.56 bpp. Также на 100% эквивалентен ASTC.

UASTC HDR 6×6 Intermediate («GPU Photo»). Быстро транскодирутся в ASTC HDR 6×6, BC6H и различные несжатые HDR-форматы.

ETC1S и UASTC LDR 4×4 могут быть транскодированы в:

  • ASTC LDR 4×4 L/LA/RGB/RGBA 8bpp
  • BC1-5 RGB/RGBA/X/XY
  • BC7 RGB/RGBA
  • ETC1 RGB, ETC2 RGBA, ETC2 EAC R11/RG11
  • PVRTC1 4bpp RGB/RGBA, PVRTC2 RGB/RGBA
  • ATC RGB/RGBA, FXT1 RGB
  • Несжатые LDR-форматы.

UASTC HDR 4×4 и UASTC HDR 6×6 могут быть транскодированы в:

  • ASTC HDR 4×4 (8bpp, только UASTC HDR 4×4)
  • ASTC HDR 6×6 RGB (3.56bpp, ASTC HDR 6×6 или UASTC HDR 6×6 intermediate)
  • BC6H RGB (8bpp, UASTC HDR 4×4 или UASTC HDR 6×6)
  • Несжатые HDR-форматы.

KTX2 и суперкомпрессия

Basis Universal — это отлично, но как с ним работать и с удобством хранить? Для упрощения этой задачи Khronos Group предложили формат контейнера KTX2, развитие KTX. Если Basis Universal — это механизм сжатия, то KTX2 — чемодан, в который можно упаковать вообще все. Он поддерживает все существующие форматы сжатия, включая ASTC, UASTC, ETC1S, BC1-7, ETC, PVRTC, и сверх того позволяет сжимать текстуры при помощи lossless-алгоритмов (Zstandard, Zlib, BasisLZ). Несжатые форматы, определенные спецификацией Vulkan, также поддерживаются в полной мере. В KTX можно хранить не только 1D-, 2D- и 3D-текстуры, но и кубические карты, mip-уровни и массивы текстур.

Khronos предоставляет набор утилит KTX Software для конвертации изображений в KTX/KTX2, а также для валидации и анализа файлов. Плюс, разумеется, библиотека libktx для декодирования файлов в приложениях — она полностью берет на себя задачу по транскодированию, и на выходе вы получаете текстуру в нужном вам формате, которую остается лишь отправить в графический API.

KTX в Dagon

Наконец-то реализовал давнюю идею поддержки текстур в формате KTX (Khronos Texture). Это контейнер, специально созданный для OpenGL и Vulkan и поддерживающий большое количество форматов текстур, включая сжатые. Особенно интересен KTX2, который позволяет хранить текстуры в формате Basis Universal — он хорош тем, что позволяет при создании игровых ресурсов не волноваться, что сжатие не будет поддерживаться на системах каких-то пользователей. Формат сжатия выбирается движком игры на основе информации от видеодрайвера, а затем текстура на лету транскодируется в этот формат. Эта фича нужна главным образом на мобильных платформах, но и в десктопном движке не помешает — Basis Universal сжимает очень эффективно и транскодируется в S3TC или BPTC за считанные мгновения.

Текстура KTX1/KTX2 загружается в объект KTXAsset, при его создании необходимо указать приоритет транскодирования. Если это TranscodePriority.Size, то загрузчик отдает предпочтение S3TC, если TranscodePriority.Quality — BPTC (при наличии поддержки). Также можно использовать TranscodePriority.Uncompressed, чтобы получить наилучшее качество — текстура будет распакована в RGBA8.

Пример:

TextureAsset aTextureBox;
TextureAsset aTextureEnvmap;

// В конструкторе сцены:

registerKTXLoader(assetManager);

// На стадии запроса ассетов:

aTextureBox = addTextureAsset("data/box.ktx2");
aTextureBox.conversion.hint = TranscodeHint.Size;

aTextureEnvmap = addTextureAsset("data/cubemap.ktx2");
aTextureEnvmap.conversion.hint = TranscodeHint.Quality;

// При создании материалов:

material.baseColorTexture = aTextureBox.texture;
environment.ambientMap = aTextureEnvmap.texture;