Any3DAny3D
·Any3D Team

Modell-Diät, Lektion 1: Die drei Waffen der Vertex-Kompression

3d-compressionvertex-compressionmeshoptdracogltf

Im vorherigen Artikel haben wir eine GLB-Datei geöffnet und gesehen, dass Texturen 80 % der Größe beanspruchen, während Vertices nur 10-20 % ausmachen. Ist Vertex-Kompression also irrelevant?

Ganz im Gegenteil. Wenn die Texturen eines Modells bereits zu KTX2 komprimiert sind und die Vertices dicht gepackt sind, sind die verbleibenden 20 % die Vertices – und diese 20 % lassen sich nochmal halbieren oder sogar um 90 % reduzieren. Noch wichtiger: Vertex-Kompression ist eine der wenigen Optimierungen, die fast kostenlos ist und sofort wirkt – ein paar Befehle, ein Decoderwechsel, und die Datei ist schlanker.

Dieser Artikel klärt drei Dinge: wie Vertex-Daten wirklich aussehen; das Temperament der drei Ansätze (Quantisierung, MeshOpt, Draco); und eine Erkenntnis, die Sie vor Fallstricken bewahrt – es gibt keine „beste" Lösung, nur die „passendste" Lösung.

Wie groß ist ein Vertex

Zuerst, was ist in einem Vertex enthalten. In glTF besteht jeder Vertex aus mehreren Attributen:

AttributZweckStandardpräzisionBytes pro Vertex
position (Position)Vertex-Koordinaten im Raum3 × float3212
normal (Normale)Bestimmt die Lichtrichtung3 × float3212
tangent (Tangente)Normal-Map-Berechnung4 × float3216
texcoord_0 (UV)Textur-Sampling-Koordinaten2 × float328
color (Vertex-Farbe)Per-Vertex-Shading4 × float3216

Ein Vertex mit dem vollständigen PBR-Attribut-Set belegt 48-64 Bytes allein für Geometrie. Ein Modell mit 100.000 Vertices ist allein durch Vertices 5-6 MB groß.

Fast alles hier verwendet float32 (32-Bit-Gleitkommazahlen). Das ist die Standardeinstellung und gleichzeitig die Angriffsfläche der Vertex-Kompression – denn die allermeisten Attribute benötigen schlicht keine 32-Bit-Präzision.

Waffe eins: Quantisierung

Quantisierung ist das zugrunde liegende Prinzip aller Vertex-Kompression; Draco und MeshOpt setzen sie intern ebenfalls ein.

Quantisierung (Mapping von hochpräzisen Floats auf niedrigpräzise Integer) läuft darauf hinaus: Für den Float 3.14159265 reicht es, sich 3.14 zu merken. Für einen Satz von Koordinaten innerhalb eines Raums verwendet man statt 32-Bit-präziser Erfassung jeder Dezimalstelle einen Integer mit kleinerem Wertebereich.

Original:  position.x = 1.234567   (float32, 4 Bytes)
Quantisert: position.x = 1234       (int16,   2 Bytes)  + ein scale/offset zur Wiederherstellung

Vorher vs. nachher:

Attributfloat32 BytesQuantisiert (16-Bit)Ersparnis
position12650%
normal126 (oder 4, mit int8 + octahedral)50-67%
tangent164-850-75%
texcoord8450%

Für den 48-64-Byte-Vertex komprimiert Quantisierung im Wesentlichen auf 16-24 Bytes, also mehr als halbiert.

Wann Quantisierung einsetzen

  • Sie wollen nur die Größe reduzieren und brauchen nicht das maximale Kompressionsverhältnis
  • Sie wollen null Decoder-Abhängigkeiten – ein quantisiertes glTF nutzt die Standard-Erweiterung KHR_mesh_quantization, die von gängigen Engines nativ unterstützt wird, ohne zusätzliche Decoder-Bibliothek
  • Ihre Zielplattform ist paketgrößenempfindlich (z. B. WeChat Mini Programs, wo ein Draco-Decoder zig KB kostet)

Wann nicht einsetzen

  • Das Modell ist winzig und Detail ist das Verkaufsargument (z. B. industrielle Bauteile im Millimeterbereich). Quantisierung verrät sich gerade bei kleinen Modellen – Texturen mögen noch gehen, aber eine Vertex-Verschiebung von 0,1 mm ist im Close-up sichtbar.

Die wahren Kosten des Präzisionsverlusts: In einer Schmuck-Szene wurde ein Ring-Modell auf 16 Bit quantisiert, und die Metallkante zeigte im Close-up Aliasing. Die Ursache waren nicht zu wenige Vertices; der Welt-Raum war zu klein, als dass 16-Bit-Integer ihn fein genug ausdrücken könnten. Abhilfe schafft, den Quantisierungsbereich zu verkleinern (die Bounding-Box von position reduzieren) oder bei kleinen Modellen die Bittiefe zu erhöhen.

Waffe zwei: MeshOpt

MeshOpt ist die offizielle glTF-Erweiterung EXT_meshopt_compression, positioniert als „anständiges Kompressionsverhältnis, rasantes Dekodieren".

Vorgehen: zuerst die Attribute quantisieren (wie oben), dann eine Technik namens Entropie-Kodierung (lossless) anwenden, um die quantisierten Integer verlustfrei nachzukomprimieren. Mit anderen Worten: verlustbehaftete Quantisierung + verlustfreie Entropie-Kodierung = kleinere Größe, gleiche Qualität wie bei reiner Quantisierung.

  • Kompressionsverhältnis: weitere 30-50 % kleiner als bei reiner Quantisierung
  • Dekodiergeschwindigkeit: extrem schnell, reines C/JS, zig Millionen Vertices pro Sekunde auf einem Thread
  • Decoder-Größe: winzig (~20-30 KB gezipt)
  • Kompatibilität: von Three.js und Babylon.js nativ unterstützt, ein De-facto-Webstandard

Wann MeshOpt einsetzen

  • Sie brauchen ein höheres Kompressionsverhältnis, können aber Dracos langsameres Dekodieren nicht akzeptieren
  • Web/Mobile/WebXR stehen im Mittelpunkt – Dekodiergeschwindigkeit wirkt sich direkt auf den First-Paint aus
  • Das Modell wird häufig dekodiert (z. B. dynamisch geladene Level)

Wann nicht einsetzen

  • Ihre Zielplattform erkennt nicht einmal EXT_meshopt_compression (selten, alte Engines)
  • Sie brauchen nur „es läuft" und der 30 %-Unterschied ist Ihnen egal – dann ist reine Quantisierung einfacher und hat eine Abhängigkeit weniger

Waffe drei: Draco

Draco ist Googles Kompressionslösung, positioniert für „maximales Kompressionsverhältnis".

Der wesentliche Unterschied zu den anderen beiden: Draco verändert die Konnektivität (Topologie) der Vertices. Quantisierung ändert nur die numerische Repräsentation jedes Vertex; MeshOpt fügt verlustfreie Kodierung hinzu; Draco reorganisiert das Dreiecksnetz und drückt „welche Vertices bilden Dreiecke" kompakter aus.

  • Kompressionsverhältnis: das höchste der drei, oft 90 %+ Reduktion bei vertex-dichten Modellen
  • Dekodiergeschwindigkeit: die langsamste der drei, aber absolut immer noch schnell
  • Decoder-Größe: größer (~100-200 KB, meist als separates wasm geladen)
  • Qualität: einstellbar, aber bei extremen Verhältnissen sieht man Verformungen

Wann Draco einsetzen

  • Extrem große, vertex-super-dichte Modelle (Millionen-Vertex-Scans, Gelände)
  • Einmaliges Laden, lange Wiederverwendung nach Dekodierung (langsameres Dekodieren akzeptabel)
  • Paketgröße ist nicht der Flaschenhals, Download-Geschwindigkeit schon

Wann nicht einsetzen

  • Mobil + schnelles First Paint nötig – man muss sowohl Decoder als auch Modell herunterladen, was ausbremst
  • Strenge Paketgrößen-Umgebungen wie Mini Programs
  • Modelle mit Skelett-Animation, Morph-Targets – Dracos Unterstützung dafür ist schwach, Fehlkonfiguration verursacht Probleme

Alle drei im Vergleich: eine Auswahl-Tabelle

Die Kompressionsverhältnisse unten referenzieren Community-Benchmarks (DeepKolos' Tests + Reddit r/threejs). Unterschiedliche Modelle variieren, aber die relativen Beziehungen sind stabil:

OptionKompressionsverhältnis (vs. float32)DekodiergeschwindigkeitDecoder-GrößeVerlustbehaftet?glTF-Erweiterung
Reine Quantisierung~50 %Nativ, kein Dekodieren0Ja (Präzision)KHR_mesh_quantization
MeshOpt~25-35 %Extrem schnell~25 KBJa (Präzision)EXT_meshopt_compression
Draco~10-20 %Schnell (langsamste der drei)~100-200 KBJa (Präzision + Topologie)KHR_draco_mesh_compression

Decoder und Plattform-Kompatibilität:

PlattformReine QuantisierungMeshOptDraco
Desktop-Web✅ Nativ✅ Nativ✅ Decoder-Konfig nötig
Mobil-Web✅ Nativ✅ Nativ⚠️ Decoder schwer
WebXR/VR✅ Nativ✅ Empfohlen⚠️ Mit Vorsicht
WeChat Mini Program✅ Empfohlen✅ Empfohlen❌ Möglichst vermeiden

Einzeiler: einfach und abhängigkeitsfrei → reine Quantisierung; ausgewogen → MeshOpt; maximales Verhältnis und Wartezeit ok → Draco.

Praxis: Quantisierung und MeshOpt mit gltfpack

gltfpack ist das offizielle glTF-Werkzeug; ein Befehl erledigt Quantisierung und MeshOpt.

Zuerst installieren (Binaries von den gltfpack-Releases):

# model.glb auf 16-Bit quantisieren und MeshOpt-Kompression hinzufügen
gltfpack -i model.glb -o model-packed.glb -cc

# -cc = compress (fügt EXT_meshopt_compression zur Standard-Quantisierung hinzu)

Häufige Parameter:

# Nur quantisieren, kein MeshOpt (am leichtesten, null Decoder-Abhängigkeit)
# gltfpack quantisiert Vertices standardmäßig auf 16 Bit (KHR_mesh_quantization),
# es ist kein extra Flag nötig
gltfpack -i model.glb -o model-quant.glb

# Quantisieren und MeshOpt aktivieren
gltfpack -i model.glb -o model-meshopt.glb -cc

# Bei sehr vielen Vertices kann man auch vereinfachen (reduziert Vertex-Zahl, verändert Modell)
gltfpack -i model.glb -o model-simplify.glb -cc -si 0.5
# -si 0.5 bedeutet Vereinfachung auf etwa 50 % der Vertices

Zu -cc: Es ist der „compress"-Schalter, der zusätzlich EXT_meshopt_compression anwendet.Ohne -cc quantisiert gltfpack trotzdem standardmäßig – das heißt, gltfpack -i in.glb -o out.glb allein ist bereits „reine Quantisierung, null Decoder-Abhängigkeit". (-v ist der ausführliche Logging-Schalter – nicht verwechseln.)

Typische Ergebnisse (ein 5-MB-, 120k-Vertex-PBR-Modell, nur als Referenz):

BehandlungDateigrößeHinweise
Original (float32)5.0 MBBasis
Reine Quantisierung (Standard)2.6 MBHalbiert, kein sichtbarer Unterschied
MeshOpt (-cc)1.7 MBWeitere 35 % gespart, minimal schneller

Hinweis: -si-Vereinfachung ist ein verlustbehafteter Vorgang, der die Geometrie verändert; er ist nicht dasselbe wie Kompression. Kompression versucht, die visuelle Treue zu bewahren; Vereinfachung entfernt aktiv Details. Beides lässt sich stapeln, hängt aber davon ab, ob die Szene es zulässt.

Häufige Fallstricke

  • Normalenrichtung nach Quantisierung verändert: meist zu geringe Präzision. Für Normalen mindestens 16 Bit oder 8-Bit-Oktahedral-Kodierung verwenden.
  • Materialien nach Draco-Dekodierung verloren: Draco komprimiert nur Meshes; Materialien und Texturen müssen separat behandelt werden. Beim Laden müssen sowohl der Draco-Decoder als auch die KHR-Erweiterungen konfiguriert sein.
  • Draco lädt in einem Mini Program nicht: der Decoder-wasm ist in manchen Laufzeiten eingeschränkt; Wechsel zu MeshOpt behebt das meist.
  • Modell „driftet" nach Quantisierung: Wenn das Modell weit vom Ursprung entfernt ist, kann 16-Bit-Präzision große Koordinaten und kleine Details nicht gemeinsam ausdrücken. Abhilfe: Modell vor dem Quantisieren in die Nähe des Ursprungs verschieben oder Bittiefe erhöhen.

Nächster Schritt

Vertices sind komprimiert – nicht zu früh feiern. Wie erwähnt, machen Texturen 80 % der Modellgröße aus. Als Nächstes wechseln wir das Schlachtfeld und betrachten, warum traditionelle PNG/JPG in den Augen der GPU ein „VRAM-Vielfraß" sind und wie GPU-native Texturformate das lösen.

Unterstützen Sie uns