diff --git a/Texture Compression/texturen-codec-vorueberlegungen.md b/Texture Compression/texturen-codec-vorueberlegungen.md new file mode 100644 index 0000000..26a3311 --- /dev/null +++ b/Texture Compression/texturen-codec-vorueberlegungen.md @@ -0,0 +1,136 @@ +# Texturoptimierung für den Web-Avatar: Codec- und Algorithmus-Vorüberlegungen + +Stand: 08.09.2026 · Vorbereitung, noch ohne Dateien +Anschluss an: `uebergabe-animationspipeline.md` + +--- + +## Kontext + +Die Animationspipeline ist abgeschlossen (88 KB pro Clip, kein Engpass mehr). +Der Fokus liegt jetzt auf den Texturen des Avatars. Die Dateien liegen noch +nicht vor — dieses Dokument hält nur die Vorüberlegungen zu Codec und +Verfahren fest, damit sie nicht verloren gehen. + +Packing und Scaling sind bereits auf dem Schirm und hier bewusst nur +gestreift. + +--- + +## Virtual Textures: nicht praktikabel + +Frage war, ob sich etwas wie Unreals Virtual Textures in three.js abbilden +lässt. + +**Kurz: nein — und für einen Avatar auch nicht das passende Werkzeug.** + +- Unreals VT setzt auf Sparse/Tiled Resources auf GPU-Ebene. WebGL2 kennt das + nicht, WebGPU exponiert es derzeit ebenfalls nicht. +- Ein Nachbau wäre möglich (Atlas + Indirection-Textur + Feedback-Pass), aber + der Feedback-Readback ist im Browser latenzbehaftet. Aufwand und Nutzen + stehen in keinem Verhältnis. +- VT lohnt sich, wenn *unique* Texturdaten das VRAM um ein Vielfaches + übersteigen — Open-World-Terrain, große Umgebungen. Ein Avatar hat 5–15 Maps. + Das Problem existiert hier nicht. + +### Was den eigentlichen Zweck erfüllt + +**Progressives Nachladen.** Erst eine 512er-Fassung zeigen, dann auf volle +Auflösung tauschen. Umsetzbar entweder über zwei separate Dateien oder, bei +KTX2, durch gezieltes Laden nur der oberen Mip-Level. + +--- + +## Mipmaps: nicht verzichtbar + +Verzicht wäre kontraproduktiv. + +- Mips kosten +33 % Speicher, machen das Sampling aber **schneller**, weil der + Texture-Cache trifft. +- Ohne Mips shimmert das Bild sichtbar, sobald die Textur verkleinert + dargestellt wird. +- Bei KTX2 sind die Mips mitkomprimiert — der Download-Aufschlag beträgt 33 % + auf die *komprimierte* Größe, nicht auf die Rohgröße. + +### Falle + +three.js kann für GPU-komprimierte Texturen **keine Mips zur Laufzeit +generieren**. Sie müssen beim Encoding in die Datei geschrieben werden. +gltfpack und `toktx` tun das per Default, aber wer sich auf +`generateMipmaps` verlässt, bekommt bei KTX2 stillschweigend keine. + +### Wo Verzicht vertretbar ist + +Nur bei Maps, die nie verkleinert dargestellt werden: LUTs, UI-Elemente, +Screen-Space-Texturen. + +### Ergänzend statt Verzicht + +`anisotropy` auf 4–8 setzen. Kostet wenig und bringt bei streifenden +Blickwinkeln deutlich mehr als jede Mip-Diskussion. + +--- + +## Codec-Optionen + +Der entscheidende Unterschied ist nicht die Dateigröße, sondern was im +**VRAM** landet. + +| Format (4K, RGBA) | Download | VRAM inkl. Mips | +|---|---|---| +| PNG | groß | ~85 MB | +| WebP / AVIF | klein | ~85 MB (dekodiert zu RGBA8) | +| KTX2 UASTC → BC7/ASTC | mittel | ~21 MB | +| KTX2 ETC1S → BC1/ETC | sehr klein | ~11 MB | + +WebP spart ausschließlich Bandbreite. KTX2 spart Bandbreite, Speicher und +Sampling-Bandbreite. Für einen Avatar mit mehreren Maps der klare Gewinner. + +### Die zwei Basis-Modi + +**ETC1S** — starke Kompression, sichtbare Artefakte an harten Kanten. +Geeignet für AO, Roughness, Metallic, Masken, oft auch Albedo. + +**UASTC** — deutlich höhere Qualität, größere Datei (mit RDO + Zstd aber +vertretbar). **Pflicht für Normal Maps.** ETC1S auf einer Normal Map erzeugt +Banding im Shading, das auf Haut sofort auffällt. + +Zusätzlich: Normal Maps als Zwei-Kanal speichern und Z im Shader +rekonstruieren. Entfernt einen kompletten Kanal als Fehlerquelle. + +--- + +## Werkzeuge + +**gltfpack** wendet Textureinstellungen global an (`-tc`, `-tu`, `-tw`). +Sobald Normal Map und ORM unterschiedlich behandelt werden sollen, reicht das +nicht mehr. + +**glTF-Transform** ist dann das bessere Werkzeug: kennt `--slots` und erlaubt +Codec, Qualität und Auflösung getrennt pro Map-Typ. + +**Alternativ:** `toktx` / `basisu` direkt auf die Einzeldateien anwenden und +das Ergebnis anschließend im glTF referenzieren. + +### three.js-Seite + +`KTX2Loader` mit `setTranscoderPath()` und `detectSupport(renderer)`. Ohne +`detectSupport` weiß der Loader nicht, ob nach BC7 oder ASTC transcodiert +werden soll. + +--- + +## Erster Schritt, sobald die Dateien da sind + +**Vor allen Codec-Feinheiten: wie viele Maps werden überhaupt gebraucht?** + +- Roughness ggf. als konstanter Faktor statt als Textur +- Metallic bei Haut ohnehin 0 +- AO teilweise verzichtbar + +Jede eingesparte Map schlägt jede Codec-Entscheidung. + +Danach dasselbe Vorgehen wie bei den Animationen: **erst messen, dann +optimieren.** Ein Inventar mit Auflösung, Kanalbelegung und tatsächlichem +Informationsgehalt pro Map. Erfahrungsgemäß sind halbleere Kanäle und +überdimensionierte Masken der häufigste Fund.