KTX2 in der Praxis: Texturkompression richtig gemacht
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:
| ETC1S | UASTC | |
|---|---|---|
| Kompressionsverhältnis | Sehr hoch (JPG-artig) | Mittel (hochwertiges PNG-artig) |
| Qualität | Für Farb-Maps ausreichend | Nahezu Originalqualität |
| VRAM (nach Transcode) | Meist 4bpp (~1/8 Original) | Meist 8bpp (~1/4 Original) |
| Kodiergeschwindigkeit | Langsam (Stufe einstellbar) | Schneller |
| Einsatz | albedo/Diffuse, emissive | normal, metalness-roughness, Daten-Maps |
| Nicht einsetzen | normals, Bilder mit exakten Werten | Farb-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):
| Format | Festplattengröße | VRAM-Nutzung (mit Mipmaps) | Upload zur GPU | Plattformübergreifend |
|---|---|---|---|---|
| PNG | ~5 MB | ~22 MB | Langsam | ✅ |
| WebP | ~1 MB | ~22 MB | Langsam | ✅ |
| KTX2 (ETC1S) | ~0.5-0.8 MB | ~2.8 MB | Schnell | ✅ |
| KTX2 (UASTC) | ~3-4 MB | ~5.6 MB | Schnell | ✅ |
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
--bcmpist der ETC1S-Modus-Schalter (Basis-Modus von Basis Universal),--uastc 1der 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 wirdsetTranscoderPathzeigt 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 = SRGBColorSpacezu setzen, lässt das ganze Bild grau und dunkel wirken. Daten-Maps (normal/roughness) bleiben stattdessenNoColorSpace(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:
| qlevel | Größe | Qualität | Kodierzeit | Einsatz |
|---|---|---|---|---|
| 128 (Standard) | Klein | Ausreichend | Mittel | Die meisten Fälle |
| 200-255 | Größer | Nahe verlustfrei | Lang (Mehrfaches) | Hohe Qualitätsanforderungen |
| 60-100 | Sehr klein | Sichtbare Blockbildung | Schnell | Fern-/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:
- Zuerst einmal mit Standardeinstellungen komprimieren und Größe und Qualität prüfen
- Nicht zufrieden →
--qlevel(ETC1S) anpassen oder--zcmp(UASTC) hinzufügen - Normal-Map matschig → bestätigen, dass UASTC verwendet wird, nicht ETC1S
- 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
--srgbvergessen (Farb-Maps brauchen es) - Einer Daten-Map (normal) versehentlich sRGB gegeben
Mipmaps fehlen, in der Ferne Flackern
- Bei der Kompression
--genmipmapnicht angehängt - Im Engine
texture.generateMipmapsnicht aktiviert (in Three.js folgt KTX2 standardmäßig der Datei, aber das Material braucht dennoch einen Mipmap-Modus fürminFilter)
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.