Any3DAny3D
·Any3D Team

KTX2 in der Praxis: Texturkompression richtig gemacht

3d-compressiontexture-compressionktx2basis-universalgltf

Der vorherige Artikel entwirrte GPU-Texturformate, Basis Universal und KTX2. Theorie klar – dieser hier ist ganz Praxis: ETC1S vs. UASTC wählen, welche Werkzeuge, welche Befehle, wie im Engine laden.

Sie können beim Lesen direkt mitmachen.

Zuerst die wichtigste Wahl: ETC1S oder UASTC

Basis bietet zwei intermediate Kodierungen. Falsch gewählt heißt nicht „nicht gut genug", sondern die Normal-Map wird Matsch. Merken Sie sich diese Tabelle:

ETC1SUASTC
KompressionsverhältnisSehr hoch (JPG-artig)Mittel (hochwertiges PNG-artig)
QualitätFür Farb-Maps ausreichendNahezu Originalqualität
VRAM (nach Transcode)Meist 4bpp (~1/8 Original)Meist 8bpp (~1/4 Original)
KodiergeschwindigkeitLangsam (Stufe einstellbar)Schneller
Einsatzalbedo/Diffuse, emissivenormal, metalness-roughness, Daten-Maps
Nicht einsetzennormals, Bilder mit exakten WertenFarb-Maps (überdimensioniert, Größe zu groß)

Warum keine ETC1S für Normal-Maps? Weil eine Normal-Map Richtungsvektoren speichert und die RGB-Kanäle jedes Pixels einander einschränken (Vektorlänge ≈ 1). ETC1S ist eine Blockkompression, die darauf zielt, „Farben richtig aussehen zu lassen"; sie ist unempfindlich gegenüber Einzelkanal-Präzision, sodass nach der Kompression die Vektorrichtung driftet und die Beleuchtung sofort falsch wirkt – besonders bei Highlight-Positionen und hochfrequenten Details. UASTC bewahrt numerische Werte besser und hält diesen Präzisionsanspruch stand.

Praxisregeln:

  • Farb-Maps (albedo, emissive) → ETC1S
  • Daten-Maps (normal, roughness, metallic, AO, thickness) → UASTC
  • Unsicher und Größe sparen → erst ETC1S probieren; bei matschigem Close-up auf UASTC wechseln

Dasselbe Bild, vier Formate verglichen

Mit einer 2048×2048-Albedo-Map als Basis (Werte sind typische Community-Werte, nur Referenz):

FormatFestplattengrößeVRAM-Nutzung (mit Mipmaps)Upload zur GPUPlattformübergreifend
PNG~5 MB~22 MBLangsam
WebP~1 MB~22 MBLangsam
KTX2 (ETC1S)~0.5-0.8 MB~2.8 MBSchnell
KTX2 (UASTC)~3-4 MB~5.6 MBSchnell

Beachten Sie, dass WebPs VRAM-Nutzung mit der von PNG identisch ist – es ist nur auf der Festplatte klein; im VRAM wird es dennoch zu Rohpixeln dekomprimiert. KTX2s ETC1S treibt Festplatte und VRAM gleichzeitig sehr weit nach unten – das macht es wertvoll.

Toolchain: drei Wege führen ans Ziel

Es gibt mehr als ein Werkzeug für die KTX2-Kompression, geordnet nach „Handlichkeit":

1. toktx (offiziell, am mächtigsten)

Das offizielle Khronos-Werkzeug, mit den meisten Parametern, geeignet für einzelne Texturen.

# PNG in eine ETC1S-kodierte KTX2 umwandeln
toktx --bcmp --uastc 0 albedo.ktx2 albedo.png

# PNG in eine UASTC-kodierte KTX2 umwandeln
toktx --uastc 1 normal.ktx2 normal.png

Häufige Parameter:

# ETC1S + Qualitätsstufe (1-255, Standard 128; höher = bessere Qualität, größere Datei)
toktx --bcmp --uastc 0 --qlevel 200 albedo.ktx2 albedo.png

# UASTC + Superkompression (Zstandard, reduziert Festplattengröße weiter)
toktx --uastc 1 --zcmp 19 normal.ktx2 normal.png

# Mipmaps automatisch erzeugen (dringend empfohlen)
toktx --bcmp --genmipmap albedo.ktx2 albedo.png

# sRGB-Farbraum angeben (für Farb-Maps Pflicht)
toktx --bcmp --srgb albedo.ktx2 albedo.png

--bcmp ist der ETC1S-Modus-Schalter (Basis-Modus von Basis Universal), --uastc 1 der UASTC-Modus. Beide schließen sich gegenseitig aus.

2. gltf-transform (am mühelosesten, dringend empfohlen)

Wenn Sie ein ganzes glTF/GLB-Modell haben, tauschen Sie mit gltf-transform in einem Befehl alle Texturen gegen KTX2 aus und wählen automatisch ETC1S/UASTC nach Texturzweck.

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

# Modell in einem Rutsch komprimieren
gltf-transform optimize model.glb model-optimized.glb \
  --texture-compress basisu

Es beurteilt intern den Texturzweck: Farb-Typen → ETC1S, Daten-Typen → UASTC, und schreibt die KHR_texture_basisu-Erweiterung automatisch. Das ist die beste Wahl für 90 % der Fälle – kein manuelles toktx-Tippen nötig.

3. Online-Werkzeuge (schnellster Einstieg)

Wenn Sie keine Umgebung einrichten wollen, nutzen Sie direkt ein Browser-Werkzeug: gltf.report (Online-gltf-transform), KTX2 Converter usw. Hochladen, herunterladen, fertig. Gut für frühe Experimente oder einmalige Aufgaben.

Vollständige Pipeline: von der Quelle bis zum Live-Gang

Hier der Standardablauf (Flussdiagramm):

Quelldatei (PNG/JPG/PSD/TGA)
        │
        ├── [ganzes Modell] gltf-transform optimize model.glb → Texturtyp automatisch erkennen
        │            └─ Farb-Maps → ETC1S
        │            └─ Daten-Maps → UASTC
        │            └─ schreibt KHR_texture_basisu-Erweiterung
        │
        └── [einzelne Textur] toktx → ETC1S/UASTC + Farbraum + Mipmap manuell angeben
        │
        ▼
Komprimierte KTX2 / GLB
        │
        ▼
Engine-Laden (Three.js / Babylon.js) ── Laufzeit-Transcode → GPU-natives Format

KTX2 in Three.js laden

Three.js unterstützt KTX2 seit r129 nativ, aber Sie müssen einen KTX2Loader bereitstellen und den Transcoder (Basis-Transcoder-wasm) konfigurieren.

import * as THREE from "three";
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module.js";

// 1. KTX2-Transcoder initialisieren und erkennen, welches native Format die GPU unterstützt
const ktx2Loader = new KTX2Loader()
  .setTranscoderPath("/basis/")            // Verzeichnis des Basis-Transcoder-wasm
  .detectSupport(renderer);                // renderer zur Fähigkeitserkennung übergeben (Pflicht)

// 2. GLTFLoader konfigurieren, KTX2/Draco/MeshOpt anhängen
const gltfLoader = new GLTFLoader();
gltfLoader.setKTX2Loader(ktx2Loader);
gltfLoader.setDRACOLoader(
  new DRACOLoader().setDecoderPath("/draco/")
);
gltfLoader.setMeshoptDecoder(MeshoptDecoder);

// 3. Modell laden; Texturen werden automatisch transcodiert
gltfLoader.load("/models/model-optimized.glb", (gltf) => {
  scene.add(gltf.scene);
});

Einige Kernpunkte:

  • detectSupport(renderer) ist Pflicht – es entscheidet, in welches native Format zur Laufzeit transcodiert wird
  • setTranscoderPath zeigt auf die Basis-Transcoder-wasm-Dateien (vom basis_transcoder-Release ins public-Verzeichnis kopieren)
  • Wenn das Modell auch Draco nutzt, auch den DRACOLoader anhängen; bei MeshOpt den MeshoptDecoder

Eine einzelne KTX2-Textur laden:

const texture = await ktx2Loader.loadAsync("/textures/albedo.ktx2");
texture.colorSpace = THREE.SRGBColorSpace;   // Farb-Maps auf sRGB setzen
material.map = texture;

Die häufigste Falle genau hier: vergessen, bei einer Farb-Map colorSpace = SRGBColorSpace zu setzen, lässt das ganze Bild grau und dunkel wirken. Daten-Maps (normal/roughness) bleiben stattdessen NoColorSpace (linear) – nicht vertauschen.

KTX2 in Babylon.js laden

Babylons Ansatz ist ähnlich, aber automatischer – KHR_texture_basisu ist im GLTFFileLoader standardmäßig aktiv, solange die Transcoder-Dateien gefunden werden.

import { Scene } from "@babylonjs/core/scene";
import { Engine } from "@babylonjs/core/Engines/engine";
import { SceneLoader } from "@babylonjs/core/Loading/sceneLoader";
import { GLTFFileLoader } from "@babylonjs/loaders/glTF/glTFFileLoader";
import "@babylonjs/loaders/glTF/2.0/Extensions/KHR_texture_basisu";

const engine = new Engine(canvas);
const scene = new Scene(engine);

SceneLoader.ImportMesh(
  "",
  "/models/",
  "model-optimized.glb",
  scene,
  (meshes) => {
    // Modell geladen; KTX2 automatisch transcodiert
  }
);

Babylon holt den Basis-Transcoder automatisch von einem CDN; für Offline-/Intranet-Umgebungen müssen Sie BASISFileLoader.TranscoderModule manuell konfigurieren.

Kompressionsparameter-Optimierung: Balance zwischen Qualität und Größe

ETC1Ss Kernparameter ist --qlevel (1-255). Auswirkung auf das Ergebnis:

qlevelGrößeQualitätKodierzeitEinsatz
128 (Standard)KleinAusreichendMittelDie meisten Fälle
200-255GrößerNahe verlustfreiLang (Mehrfaches)Hohe Qualitätsanforderungen
60-100Sehr kleinSichtbare BlockbildungSchnellFern-/kleine Texturen

UASTCs Größe ist relativ fest; Sie steuern die Festplattengröße hauptsächlich über --zcmp (Zstandard-Superkompression), was den VRAM nicht beeinflusst (nach Dekomprimierung weiterhin 8bpp).

Empfohlene Optimierungsreihenfolge:

  1. Zuerst einmal mit Standardeinstellungen komprimieren und Größe und Qualität prüfen
  2. Nicht zufrieden → --qlevel (ETC1S) anpassen oder --zcmp (UASTC) hinzufügen
  3. Normal-Map matschig → bestätigen, dass UASTC verwendet wird, nicht ETC1S
  4. Farben zu dunkel → Farbraum-Einstellungen prüfen (sRGB-Flag, colorSpace im Engine)

Häufige Fehlerbehebung

Transcode-Fehlschlag / Ladefehler

  • Prüfen, ob der Transcoder-wasm-Pfad stimmt (Three.js braucht setTranscoderPath)
  • Prüfen, ob die Engine-Version die aktuelle KTX2-Version unterstützt (ältere Basis-Kodierungen werden von neueren Transcodern nicht unterstützt)
  • Die Konsole zeigt meist einen konkreten Fehler; nach Schlagwort suchen

Farben zu dunkel / zu hell

  • Eine Farb-Map (albedo) wurde nicht auf sRGB gesetzt oder vertauscht
  • Bei toktx --srgb vergessen (Farb-Maps brauchen es)
  • Einer Daten-Map (normal) versehentlich sRGB gegeben

Mipmaps fehlen, in der Ferne Flackern

  • Bei der Kompression --genmipmap nicht angehängt
  • Im Engine texture.generateMipmaps nicht aktiviert (in Three.js folgt KTX2 standardmäßig der Datei, aber das Material braucht dennoch einen Mipmap-Modus für minFilter)

Normalenrichtung im Close-up falsch

  • Normal-Map hat ETC1S verwendet; auf UASTC wechseln
  • Bestätigen, dass die Normal-Map OpenGL-Stil ist (Grün-Kanal nach oben); DirectX-Stil muss in manchen Engines den G-Kanal umkehren

Datei wurde stattdessen größer

  • Kleine Texturen (< 128×128) lohnen kein KTX2 – Blockkompression hat feste Overhead-Kosten und füllt einen ganzen Block
  • Einfarbige Texturen nicht als KTX2 komprimieren; ein Material-Farbwert ist billiger

Nächster Schritt

Damit ist die Texturkompression im Wesentlichen erledigt. Aber „zu wissen, wie man Werkzeuge bedient" ist nicht dasselbe wie „die richtigen Werkzeuge zu verwenden" – der nächste Artikel bündelt das Wissen der vorherigen vier in einen Auswahl-Rahmen: Desktop, Mobil, VR, Mini Programs – welche Kombination in welchem Szenario.

Unterstützen Sie uns