Any3DAny3D
·Any3D Team

KTX2 na Prática: A Forma Correta de Fazer Compressão de Texturas

3d-compressiontexture-compressionktx2basis-universalgltf

O artigo anterior desenrolou os formatos de textura de GPU, Basis Universal e KTX2. A teoria está clara; este é todo prático: como escolher entre ETC1S e UASTC, quais ferramentas usar, quais comandos digitar e como carregar no engine.

Você pode acompanhar e fazer ao mesmo tempo que lê.

Primeiro, a escolha mais importante: ETC1S ou UASTC

O Basis oferece duas codificações intermediárias. Escolha errado e não é "não é bom o suficiente"—seu normal map simplesmente vira lama. Memorize esta tabela:

ETC1SUASTC
Taxa de compressãoMuito alta (como JPG)Média (qualidade alta, como PNG)
QualidadeBoa para mapas de coresQualidade quase original
VRAM (após transcodificação)Geralmente 4bpp (~1/8 do original)Geralmente 8bpp (~1/4 do original)
Velocidade de codificaçãoLenta (nível ajustável)Mais rápida
Usar paraalbedo/difuso, emissivenormal, metalness-roughness, mapas de dados
Não usar paranormais, imagens que precisam de valores precisosMapas de cores (exagero, tamanho fica grande)

Por que normais não podem usar ETC1S? Porque um normal map armazena vetores de direção, e os canais RGB de cada pixel se restringem mutuamente (comprimento do vetor ≈ 1). ETC1S é uma compressão por blocos projetada para fazer "cores parecerem corretas"; ela não é sensível à precisão de canal único, então após a compressão a direção do vetor se desvia e a iluminação imediatamente fica errada—especialmente posições de destaque e detalhes de alta frequência. UASTC preserva valores numéricos melhor e se sustenta nessa demanda de precisão.

Regras práticas:

  • Mapas de cores (albedo, emissive) → ETC1S
  • Mapas de dados (normal, roughness, metallic, AO, thickness) → UASTC
  • Não tem certeza mas quer economizar tamanho → tente ETC1S primeiro; se um close-up ficar borrado, mude para UASTC

Uma imagem, quatro formatos comparados

Usando um mapa albedo de 2048×2048 como linha de base (valores são números típicos da comunidade, apenas para referência):

FormatoTamanho no discoUso de VRAM (com mipmaps)Upload para GPUCross-platform
PNG~5MB~22MBLento
WebP~1MB~22MBLento
KTX2 (ETC1S)~0.5-0.8MB~2.8MBRápido
KTX2 (UASTC)~3-4MB~5.6MBRápido

Note que o uso de VRAM do WebP é o mesmo do PNG—é só pequeno no disco; na VRAM ele ainda descomprime para pixels brutos. O KTX2 com ETC1S reduz tanto o disco quanto a VRAM muito baixo de uma vez—é isso que o torna valioso.

Cadeia de ferramentas: todos os caminhos levam lá

Há mais de uma ferramenta para comprimir KTX2, ordenadas por "facilidade de obter":

1. toktx (oficial, mais poderoso)

A ferramenta oficial do Khronos, com mais parâmetros, adequada para processar texturas individualmente.

# Convert PNG to an ETC1S-encoded KTX2
toktx --bcmp --uastc 0 albedo.ktx2 albedo.png

# Convert PNG to a UASTC-encoded KTX2
toktx --uastc 1 normal.ktx2 normal.png

Parâmetros comuns:

# ETC1S + quality level (1-255, default 128; higher = better quality and larger size)
toktx --bcmp --uastc 0 --qlevel 200 albedo.ktx2 albedo.png

# UASTC + supercompression (Zstandard, further shrinks disk size)
toktx --uastc 1 --zcmp 19 normal.ktx2 normal.png

# Auto-generate mipmaps (strongly recommended)
toktx --bcmp --genmipmap albedo.ktx2 albedo.png

# Specify sRGB color space (required for color maps)
toktx --bcmp --srgb albedo.ktx2 albedo.png

--bcmp é a chave do modo ETC1S (modo base do Basis Universal), e --uastc 1 é o modo UASTC. Os dois são mutuamente exclusivos.

2. gltf-transform (mais fácil, altamente recomendado)

Se você tem um modelo glTF/GLB inteiro, use gltf-transform para trocar todas as suas texturas por KTX2 em um único comando, escolhendo automaticamente ETC1S/UASTC pela finalidade da textura.

# Install
npm install -g @gltf-transform/cli

# One-shot compress the whole model
gltf-transform optimize model.glb model-optimized.glb \
  --texture-compress basisu

Ele julga internamente a finalidade da textura: tipos de cores usam ETC1S, tipos de dados usam UASTC, e escreve a extensão KHR_texture_basisu automaticamente. Esta é a melhor escolha para 90% dos casos—não precisa digitar toktx manualmente um por um.

3. Ferramentas online (mais rápido para começar)

Quando não quer configurar um ambiente, use uma ferramenta de navegador: gltf.report (gltf-transform online), KTX2 Converter, etc. Envie, baixe, pronto. Bom para experimentos iniciais ou tarefas pontuais.

Fluxo completo: da origem à produção

Aqui está o fluxo padrão (diagrama de fluxo):

Arquivo de origem (PNG/JPG/PSD/TGA)
        │
        ├── [modelo inteiro] gltf-transform optimize model.glb → detectar tipo de textura automaticamente
        │            └─ mapas de cores → ETC1S
        │            └─ mapas de dados → UASTC
        │            └─ escreve extensão KHR_texture_basisu
        │
        └── [textura única] toktx → especificar manualmente ETC1S/UASTC + espaço de cores + mipmap
        │
        ▼
KTX2 / GLB comprimido
        │
        ▼
Carregamento no engine (Three.js / Babylon.js) ── transcodificação em tempo real → formato nativo da GPU

Carregando KTX2 no Three.js

O Three.js suporta KTX2 nativamente desde a r129. Anexe um KTX2Loader—apontando para o wasm do transcodificador Basis e sondando o suporte da GPU—ao GLTFLoader; qualquer glTF com texturas KTX2 então transcodifica automaticamente na hora do carregamento.

const ktx2Loader = new KTX2Loader().setTranscoderPath("/basis/").detectSupport(renderer);
gltfLoader.setKTX2Loader(ktx2Loader); // also attach DRACOLoader / MeshoptDecoder if the model uses them

detectSupport(renderer) é obrigatório—ele decide para qual formato nativo transcodificar. E defina as mapas de cores com texture.colorSpace = THREE.SRGBColorSpace; pular isso é o bug clássico de "tudo parece cinza" (mapas de dados como normal/roughness ficam em linear).

Carregando KTX2 no Babylon.js

Babylon é ainda mais fácil—GLTFFileLoader habilita KHR_texture_basisu por padrão e busca automaticamente o transcodificador Basis de uma CDN, então glTFs com texturas KTX2 simplesmente funcionam. Para ambientes offline/intranet, configure manualmente BASISFileLoader.TranscoderModule.

Ajuste de parâmetros de compressão: equilibrando qualidade e tamanho

O parâmetro principal do ETC1S é --qlevel (1-255). Como ele afeta o resultado:

qlevelTamanhoQualidadeTempo de codificaçãoCaso de uso
128 (padrão)PequenoAdequadaMédioMaioria dos casos
200-255MaiorQuase sem perdasLonga (várias vezes)Requisitos de alta qualidade
60-100Muito pequenoBloqueio visívelRápidaTexturas distantes/pequenas

O tamanho do UASTC é relativamente fixo; você ajusta principalmente o tamanho no disco com --zcmp (supercompressão Zstandard), que não afeta a VRAM (continua 8bpp após descompressão).

Ordem recomendada de ajuste:

  1. Primeiro comprima uma vez com os padrões e verifique tamanho e qualidade
  2. Não satisfeito → ajuste --qlevel (ETC1S) ou adicione --zcmp (UASTC)
  3. Normal map ficou borrado → confirme que está usando UASTC, não ETC1S
  4. Cores parecem escuras → verifique as configurações de espaço de cores (flag sRGB, colorSpace no engine)

Solução de problemas comuns

Falha na transcodificação / erro de carregamento

  • Verifique se o caminho do wasm do transcodificador está correto (Three.js precisa de setTranscoderPath)
  • Verifique se a versão do seu engine suporta a versão atual do KTX2 (codificações Basis mais antigas não são suportadas por transcodificadores mais novos)
  • O console geralmente tem um erro específico; busque por palavra-chave

Cores muito escuras / muito claras

  • Uma mapa de cores (albedo) não foi definida como sRGB, ou foi definida ao contrário
  • Você esqueceu --srgb no toktx (mapas de cores precisam dele)
  • Um mapa de dados (normal) recebeu sRGB por engano

Mipmaps ausentes, cintilação à distância

  • A compressão não adicionou --genmipmap
  • O engine não habilitou texture.generateMipmaps (no Three.js, KTX2 segue o arquivo por padrão, mas o minFilter do material ainda precisa de um modo de mipmap)

Direção da normal errada em close-up

  • O normal map usou ETC1S; mude para UASTC
  • Confirme que o normal map é estilo OpenGL (canal verde para cima); estilo DirectX precisa do canal G invertido em alguns engines

Arquivo ficou maior

  • Texturas pequenas (< 128×128) não valem o KTX2—compressão por blocos tem sobrecarga fixa e preenche um bloco inteiro
  • Não use KTX2 em textura de cor sólida; usar um valor de cor no material é mais barato

Próximo passo

Isso basicamente encerra a compressão de texturas. Mas "saber como usar as ferramentas" não é o mesmo que "usar as ferramentas certas"—o próximo artigo junta todo o conhecimento dos quatro anteriores em um framework de seleção: desktop, mobile, VR, Mini Programas—exatamente qual combinação cada cenário deve usar.

Apoie-nos