Any3DAny3D
·Any3D Team

Von Blender bis zum Live-Gang: ein End-to-End-Kompressions-Walkthrough

3d-compressionpipelinetexture-compressionvertex-compressiongltf

An diesem Punkt der Serie sind Werkzeuge, Prinzipien und Auswahl behandelt. In diesem letzten Artikel binden wir alles zu einer lauffähigen Pipeline zusammen: Ausgehend von einem realen Blender-Modell Schritt für Schritt komprimieren, bei jedem Schritt Dateigröße, VRAM und Ladezeit aufzeichnen und schließlich sehen, ob es sich von einem 50-MB-Schwergewicht zu einem 5-MB-Modell schrumpfen lässt, das auf dem Handy sofort öffnet.

Zielleser: wer die vorherigen fünf gelesen hat und wirklich loslegen will. Keine neuen Konzepte hier – nur kopierbare Abläufe, Befehle und Skripte.

Startpunkt: ein reales PBR-Modell

Als Sample ein sehr typisches E-Commerce-Demo-Modell: ein hochdetailliertes Produktmodell mit vollständigen PBR-Maps.

AnfangsmetrikWert
Blender-Quelldatei~120 MB (inkl. nicht exportierter High-Poly)
Exportiertes GLB (float32 + PNG)~50 MB
Vertex-Anzahl~180k
Maps6 × 4096×4096 (albedo, normal, roughness, metallic, AO, emissive)
VRAM-Nutzung (6 vollständig dekomprimiert)~520 MB
ZielDatei ≤ 5 MB, VRAM kontrollierbar, auf Mobil sofort öffnen

Eine 50-MB-Datei und 520 MB VRAM – dieses Modell crash auf Mobil garantiert. Gehen wir Schritt für Schritt vor.

Schritt 0: korrekt aus Blender exportieren

Die erste Hürde der Kompression ist tatsächlich der Export; viele bluten hier.

Wichtige Einstellungen beim glTF-Export aus Blender:

  • Format: glTF Binary (.glb) (einzelne Datei, einfach zu übertragen)
  • Geometrie: Normals, Tangents anhaken (PBR-Normal-Maps brauchen Tangenten)
  • UV: sicherstellen, dass exportiert wird (standardmäßig an)
  • Texturen: Automatic oder JPEG (das Texturformat hier ist egal; wir komprimieren später neu – aber sie müssen exportiert sein)
  • Kompression: Blender-eigene Mesh-Kompression nicht anhaken; wir nutzen spezialisierte Werkzeuge
  • Transform: +Y Up (glTF-Standard)
  • Daten: nur Nötiges anhaken (Animation, Kameras, Lichter bei Nichtbedarf nicht exportieren, um Größe zu reduzieren)

Nach dem Export model.glb: 50 MB, 6 PNG-Maps, float32-Vertices. Das ist unsere Basis.

Die erste häufige Falle liegt genau hier: Blender exportiert standardmäßig ungenutzte Meshes und verborgene Hilfsobjekte ebenfalls. Vor dem Export File > Clean Up > Purge Orphans ausführen und im Outliner nur die zu exportierenden Objekte auswählen.

Die End-to-End-Pipeline, Gesamtbild

Die ganze Linie zeichnen, damit Sie ein mentales Bild haben:

Blender-Quelldatei
   │  .glb exportieren (float32 + PNG)            50 MB
   ▼
[1] Dedup + doppelte Vertices verschweißen (gltf-transform)   ~45 MB
   │
[2] Vertex-Kompression: MeshOpt (gltfpack / gltf-transform) ~30 MB
   │
[3] Texturkompression: PNG → KTX2 (ETC1S/UASTC)     ~6 MB
   │
[4] (optional) Geometrie-Vereinfachung LOD (simplify)   ~4-5 MB
   ▼
Final model-final.glb                          ~5 MB
   │
Engine-Laden (Three.js / Babylon.js) → Laufzeit-Transcode → Live

Die Zahlen jedes Schritts werden unten in Tabellen live verfolgt.

Toolchain: welche wählen

Es gibt mehrere Kompressions-Werkzeuge; hier ein Vergleich, damit Sie nicht falsch wählen:

WerkzeugStärkeSchwächeGut für
gltf-transformAllrounder, Texturen+Vertices in einem Abwasch; API-fähig, skriptbarTop-Verhältnis unter SpezialwerkzeugenEmpfohlenes Hauptwerkzeug für die meisten Szenarien
gltfpackVertex-Profi, nativ MeshOptSchwache TexturkompressionVertex-dicht, feine MeshOpt-Kontrolle
toktxProfessionellste Texturkompression, meisten ParameterNur Texturen, nicht ganze ModelleEinzeltextur-Feintuning
gltf-pipelineVeteran, unterstützt DracoInaktive Wartung, wenig FeaturesBestehende Draco-Legacy-Projekte
Online-Werkzeuge (gltf.report)Null-InstallationNicht für Automatisierung/MasseExperimente, einmalige Aufgaben

Hauptempfehlung: den ganzen Ablauf mit gltf-transform fahren; bei Bedarf mit gltfpack Vertices, mit toktx Einzeltexturen nachschärfen. Alle Schritte unten basieren auf gltf-transform.

Schritt 1: Dedup + Verschweißen

Modelle haben oft doppelte Vertices, ungenutzte Knoten und Materialien. Erst einmal reinigen.

gltf-transform optimize model.glb step1.glb --weld --prune
StufeDateigrößeVRAMÄnderung
Basis50 MB~520 MB
Step 1 Dedup45 MB~520 MB-5 MB (VRAM unverändert, da Texturen noch da)

VRAM bewegte sich kaum – wie erwartet. Dedup spert hauptsächlich Vertices und Struktur; Texturen sind der VRAM-Schwergewichtler.

Schritt 2: Vertex-Kompression MeshOpt

gltf-transform optimize step1.glb step2.glb --meshopt --weld --prune

--meshopt quantisiert Vertices auf 16 Bit und wendet MeshOpt-verlustfreie Kodierung an und fügt automatisch die EXT_meshopt_compression-Erweiterung hinzu.

StufeDateigrößeVRAMÄnderung
Step 145 MB~520 MB
Step 2 + MeshOpt30 MB~520 MB-15 MB (Vertex-Anteil)

VRAM noch ~520 MB? Richtig – denn Vertices sind ein kleiner Anteil des VRAM (10-20 %); sie zu schneiden hat begrenzten VRAM-Effekt. Das echte VRAM-Monster sind Texturen, als Nächstes behandelt.

Schritt 3: Texturkompression PNG → KTX2

Dieser Schritt ist der König der Kosten-Nutzen.

gltf-transform optimize step2.glb step3.glb \
  --texture-compress basisu \
  --meshopt --weld --prune

--texture-compress basisu erkennt jede Map automatisch: Farb-Maps (albedo, emissive) → ETC1S; Daten-Maps (normal, roughness, metallic, AO) → UASTC.

StufeDateigrößeVRAMÄnderung
Step 230 MB~520 MB
Step 3 + KTX26 MB~70 MB-24 MB Datei / -450 MB VRAM

Dieser Schritt ist der Wendepunkt der gesamten Pipeline:

  • Datei fällt von 30 MB auf 6 MB
  • VRAM fällt von 520 MB auf ~70 MB – weil die sechs 4096-Maps von „dekomprimierten Rohpixeln" zu „blockkomprimiert" wechseln, jede von ~87 MB auf ~11-14 MB

Der VRAM sinkt um eine Größenordnung – das ist der Schlüssel, ob es auf Mobil läuft.

Schritt 4: (optional) Geometrie-Vereinfachung

Wenn Sie noch kleiner wollen und die Szene eine Verringerung der Vertex-Präzision zulässt, fügen Sie Geometrie-Vereinfachung hinzu.

gltf-transform optimize step3.glb final.glb \
  --texture-compress basisu \
  --meshopt \
  --simplify --simplify-ratio 0.5 \
  --weld --prune

--simplify-ratio 0.5 bedeutet, etwa 50 % der Vertices zu behalten.

StufeDateigrößeVRAMÄnderung
Step 36 MB~70 MB
Step 4 + Vereinfachung 0.54.5 MB~70 MB-1.5 MB (VRAM grob unverändert)

Vereinfachung spart hauptsächlich Dateigröße; der VRAM-Effekt ist gering. Der Preis ist reduziertes Modelldetail – aus der Nähe sichtbar. E-Commerce-Produktseiten sollte man üblicherweise nicht übervereinfachen; Gebäude/große Szenen passen sehr gut.

Vollständige Effekt-Tabelle

Die vier Schritte übereinandergelegt für das Gesamtbild (basierend auf obigem Sample; Zahlen sind Größenordnungs-Illustration):

SchrittDateigrößeVRAMKumulierte Reduktion
Basis (float32 + PNG)50 MB~520 MB
+ Dedup & Verschweißen45 MB~520 MB-10 %
+ MeshOpt-Vertices30 MB~520 MB-40 %
+ KTX2-Texturen6 MB~70 MB-88 % Datei / -87 % VRAM
+ Geometrie-Vereinf. (0.5)4.5 MB~70 MB-91 % Datei

Fazit: Texturkompression liefert den ganz überwiegenden Anteil der Größen- und VRAM-Gewinne. Vertex-Kompression ist das Icing; Texturkompression ist die Rettung. Das deckt sich vollständig mit der These des ersten Artikels – Texturen sind 80 % der Größe, also ist ihre Optimierung am rentabelsten.

Ein-Befehl-Version: bequemer Ein-Klick

Wenn Sie nicht schrittweise vorgehen wollen, alle Optimierungen auf einmal:

gltf-transform optimize model.glb model-final.glb \
  --texture-compress basisu \
  --meshopt \
  --simplify --simplify-ratio 0.5 \
  --weld --prune

Dieser eine Befehl = Dedup + Verschweißen + Vertex-MeshOpt + Textur-KTX2 + Geometrie-Vereinfachung. Er reicht für 90 % der Szenarien; die Schritte dienen vor allem dem Verständnis und dem Tuning.

Automatisierungs-Skript: wiederverwendbar

Den Ablauf in ein Skript kapseln, das sich in den Build einbauen lässt. Dieses Skript gibt pro Zielplattform eine andere Version aus und druckt den Effekt jedes Schritts.

// scripts/compress-model.mjs
import { optimize } from "@gltf-transform/functions";
import { NodeIO } from "@gltf-transform/core";
import { KHRONOS_EXTENSIONS } from "@gltf-transform/extensions";
import { filesize } from "filesize";

const io = new NodeIO().registerExtensions(KHRONOS_EXTENSIONS);

// Kompressionsstrategien je Plattform
const PROFILES = {
  mobile: {
    textureCompression: "basisu",
    meshCompression: "meshopt",
    simplify: { ratio: 0.5 },
    weld: true,
    prune: true,
  },
  vr: {
    textureCompression: "basisu",
    meshCompression: "meshopt",
    // VR-Nahansicht, keine Vereinfachung
    simplify: null,
    weld: true,
    prune: true,
  },
  desktop: {
    textureCompression: "webp",
    meshCompression: "meshopt",
    simplify: null,
    weld: true,
    prune: true,
  },
};

async function compress(inputPath, profileName) {
  const cfg = PROFILES[profileName];
  const doc = await io.read(inputPath);
  const before = Buffer.byteLength(await io.writeBinary(doc), "utf8");

  await optimize(doc, {
    textureCompression: cfg.textureCompression,
    meshCompression: cfg.meshCompression,
    simplify: cfg.simplify ?? undefined,
    weld: cfg.weld,
    prune: cfg.prune,
  });

  const bytes = await io.writeBinary(doc);
  const outPath = inputPath.replace(/\.glb$/, `-${profileName}.glb`);
  await io.write(outPath, doc);
  const after = bytes.byteLength;

  console.log(
    `${profileName.padEnd(8)} ${filesize(before)} → ${filesize(after)} ` +
      `(${Math.round((1 - after / before) * 100)}% smaller) → ${outPath}`
  );
}

// Verwendung: node scripts/compress-model.mjs path/to/model.glb
const input = process.argv[2];
for (const profile of Object.keys(PROFILES)) {
  await compress(input, profile);
}

Ins Projekt einbauen:

node scripts/compress-model.mjs public/models/model.glb
# mobile   50 MB → 4.5 MB (91 % kleiner) → model-mobile.glb
# vr       50 MB → 6.2 MB (87 % kleiner) → model-vr.glb
# desktop  50 MB → 11 MB (78 % kleiner)  → model-desktop.glb

Das Frontend lädt zur Laufzeit einfach die passende Version pro Gerät.

Möchten Sie diese Pipeline nicht selbst bauen? Any3Ds Online-Tool erledigt alles Obige in einem Aufwasch – GLB hochladen, automatisch Textur-KTX2 + Vertex-MeshOpt laufen lassen und komprimierte Versionen pro Plattform ausgeben, ohne lokalen Toolchain-Aufwand.

Häufige Fallstricke FAQ

Modell wird schwarz / Texturen nach Kompression nicht angezeigt

  • 99 % Farbraum: einer Farb-Map fehlt sRGB. In Three.js texture.colorSpace = THREE.SRGBColorSpace.
  • Bei toktx Farb-Maps --srgb vergessen.

Beleuchtung nach Normal-Map-Kompression falsch

  • Normal-Map nutzte ETC1S; auf UASTC wechseln.
  • Normal-Map ist DirectX-Stil (Grün-Kanal nach unten); Engine will OpenGL-Stil, G-Kanal umkehren.

Mobil-Laden hängt beim First Paint

  • Prüfen, ob der Draco-Decoder-wasm geladen wird (zusätzlicher Request). Auf Mobil MeshOpt bevorzugen.
  • KTX2-Transcoder-Pfad falsch konfiguriert; Transcode schlägt fehl und fällt auf CPU-Dekodierung zurück.

Komprimierte Datei wurde größer

  • Map zu klein (< 128 px); KTX2 lohnt sich nicht – Blockkompression hat feste Overhead-Kosten.
  • Modell war schon einmal komprimiert; ein zweiter Durchgang bringt keinen Gewinn (sogar negativ).

Modell bricht nach Vereinfachung

  • --simplify-ratio zu niedrig; auf 0.7-0.8 erhöhen.
  • Vereinfachung ist freundlich zu harten Oberflächen (Maschinen, Architektur) und bricht bei organischen Kurven (Charakteren) leicht.

KTX2 lädt in manchen Browsern nicht

  • Alter Safari / alte WebView unterstützen es nicht. PNG/WebP-Fallback bereithalten oder über das fallback-Feld von KHR_texture_basisu ein Sicherheitsnetz bieten.

Serien-Spickzettel

Das Wesen aller sechs Artikel in einer Tabelle kondensiert – bookmarken.

Größen-Zusammensetzung

BestandteilAnteilOptimierungs-Werkzeug
Textur-Maps70-85 %KTX2 (größter Gewinn)
Vertex-Daten10-20 %MeshOpt / Quantisierung / Draco
Animationsdaten0-15 %Keyframes reduzieren / komprimieren
Sonstiges< 2 %Dedup

VRAM-Formel

VRAM traditioneller Formate = Breite * Höhe * 4 Bytes * 1.333 (mit Mipmaps)
KTX2 blockkomprimierter VRAM ≈ obiges / 4 (ETC1S) oder / 2 (UASTC)

Vertex-Kompressions-Auswahl

SzenarioEmpfehlung
Null-Abhängigkeit, am einfachstenReine Quantisierung (KHR_mesh_quantization)
Ausgewogener Web-ErstfavoritMeshOpt
Max-Verhältnis, Decode-Wartezeit okDraco
Mini Program / paketempfindlichReine Quant. / MeshOpt; Draco vermeiden

Texturkompressions-Auswahl

Map-TypEmpfohlene Kodierung
albedo / emissive (Farbe)KTX2 ETC1S
normal / roughness / metallic / AO (Daten)KTX2 UASTC
Desktop-Web, Download-GeschwindigkeitWebP / AVIF
Kleine Maps (< 128 px)PNG belassen, kein KTX2

Ein-Klick-Befehl

# Volle Optimierung (Textur + Vertex + Vereinfachung)
gltf-transform optimize model.glb model-final.glb \
  --texture-compress basisu --meshopt \
  --simplify --simplify-ratio 0.5 --weld --prune

Plattform-Spickzettel

PlattformTexturVertex
Desktop-WebWebP / KTX2MeshOpt
Mobil-WebKTX2 PflichtMeshOpt
VRKTX2 PflichtMeshOpt + LOD
Mini ProgramKTX2 / WebPMeshOpt / Quantisierung
Große SzeneKTX2 PflichtMeshOpt + Draco + LOD

Serien-Rückblick

Sechs Artikel geschafft; zusammengefügt eine vollständige Kette:

  1. Warum so schwer: Größen-Zusammensetzung und die VRAM-Wahrheit klären
  2. Drei Waffen der Vertex-Kompression: Prinzipien und Wahl von Quantisierung, MeshOpt, Draco
  3. Das Textur-VRAM-Problem: warum PNG/JPG in den Augen der GPU schuldig sind
  4. KTX2 in der Praxis: ETC1S/UASTC-Auswahl, Toolchain, Engine-Laden
  5. Auswahl-Leitfaden: ein Entscheidungsrahmen nach Plattform/Szenario
  6. Dieser Artikel: End-to-End-Pipeline, von Blender bis Live

Der Kern ist ein Satz: erst den Flaschenhals durchdenken (Download/VRAM/Framerate), dann Werkzeuge wählen; Texturkompression bringt die größte Rendite, Vertex-Kompression ist Icing; verschiedene Plattformen, verschiedene Schicksale – keine Pauschallösung.

Mit dem Skript und Spickzettel dieses Artikels sollte es ein reproduzierbarer Weg sein, Ihr Modell von 50 MB auf 5 MB und den VRAM von 520 MB auf 70 MB zu bringen. Der Rest ist nur noch Tun.

Unterstützen Sie uns