Werkstattbericht · Generative Reihe · Maierzone 2026
Generativ auf MZP
Stack & Fallstricke
Was der Mzone Publisher für generative Arbeiten hergibt — und was beim Bauen
von Morphogenesis, Dispersion Cathedral und Chladni
tatsächlich wehgetan hat. Dreiundzwanzig Einträge, jeder aus einem konkreten Fehlschlag.
mzone-ui 1.8.0 · three 0.170.0 · 23 Einträge · Stand 2026-08-31
So liest sich ein Eintrag
F·08errorsubject: CONSOLE_ERROR⬡
Fehler abfangen, nicht loggen
Befund
Die Initialisierung wirft, der statische Ersatz greift korrekt — aber ein console.error im catch bleibt stehen.
Folge
Der Render-Check meldet CONSOLE_ERROR, obwohl die Seite genau das tut, was sie soll.
Kur
Init in try/catch, im Fehlerfall den Ersatz zeigen — und im catchschweigen.
◆ Morphogenesis
▲ Dispersion Cathedral
● Chladni
⬡ allgemein / Publisher
Jeder Fallstrick trägt das Zeichen der Arbeit, an der er gelernt wurde. Die
Kur-Zeile
ist der Fix, nichts sonst.
§ 01
Was ausgeliefert wird
Fünf Bibliotheken liegen unter /lib/ — selbst gehostet, ohne CDN,
ohne Netzabhängigkeit. Ein Bundle bindet sie mit relativen Pfaden ein und läuft
offline im Prüf-Browser genauso wie im Netz.
Bibliothek
Version
Einstieg
three
0.170.0
/lib/three@0.170.0/three.module.js
d3
7.9.0
/lib/d3@7.9.0/d3.min.js
chart.js
4.4.6
/lib/chart.js@4.4.6/chart.umd.js
mzone-ui
1.8.0
/lib/mzone-ui@1.8.0/mzone.css
fonts-maierzone
1.0.0
Space Grotesk · Inter · Instrument Serif · IBM Plex Mono
10 MB
entpackt, gesamt je Bundle
64
Dateien je Bundle
1
index.html, genau eine
5
Versionen je Slug (dann rollt es)
Schriften kommen aus fonts.css, nicht aus mzone.css.
Dort liefert fonts.css vier selbst gehostete Familien (SIL OFL);
in mzone.css ist --mz-font nur ein
System-Stack. Für einen eigenen Auftritt beide Dateien verlinken — Instrument Serif
trägt Werktexte spürbar besser als der System-Serif.
Die fx-Module sind für Reports gedacht.fluidField, glass,
particleField, glyphRain,
dither, asciify … — für eigenständige
Arbeiten zu generisch. Eigenes GLSL schreiben; die Bibliothek nur fürs Gerüst
(mz-body, mz-page) und die
Barrierefreiheit (mz-sr-only) nutzen.
§ 02
Branding als Palette
Vier eigenständige Profile stehen bereit. nightline — Petrol
#2F6F63, Gold #E8B34C, Surface
#14181B — ist als Ops-Dashboard gedacht, trägt aber als
Kunstpalette überraschend weit; alle drei bisherigen Arbeiten stehen darauf.
Die Profile sind laut Publisher ausdrücklich eine Basis, kein Regelwerk:
einzelne Tokens dürfen verstellt werden.
nightlineledgermonoblockarcade
Diese Seite nimmt nightline und erweitert es um einen Rostton
(#CE6B44) für die Stufe error — genau die Freiheit,
die das Profil einräumt.
§ 03
Fallstricke
Dreiundzwanzig Einträge in fünf Gruppen. error
heißt: der Render-Check schlägt an oder das Bild bleibt schwarz.
warn
heißt: es rendert, sieht aber falsch aus.
info
ist ein Kniff, der Arbeit spart.
APräzision & Farbe
F·01warnsubject: HALF_FLOAT⬡
Half-Float statt Float
Befund
Echtes FloatType mit linearer Filterung braucht eine Extension und ist nicht überall da.
Folge
Nahe 1.0 liegt die Auflösung von Half-Float bei rund 0.001; kleinere Simulationsschritte verschwinden ersatzlos.
Kur
Render-Targets als THREE.HalfFloatType. Schrittweiten nicht unter etwa 0.005.
F·02warnsubject: COLOR_SPACE⬡
Farbraum einmal festlegen
Befund
Ohne gesetzten Output-Farbraum wandelt three zweimal um.
Folge
Alles wird flau.
Kur
renderer.outputColorSpace = THREE.LinearSRGBColorSpace setzen und Farben direkt in sRGB schreiben.
F·03infosubject: FIREFLIES▲
Ausreißer klammern
Befund
Einzelne Pixel, deren gebrochener Strahl über eine Facettenkante genau die Lichtquelle trifft, blitzen als weiße Punkte.
Folge
Die Arbeit sieht verrauscht aus, obwohl sie es nicht ist.
Kur
min(farbe, vec3(6.0)) am Ende jedes Strahlengangs.
F·04warnsubject: SDF_RECT⬡
Rechteck-SDF vollständig schreiben
Befund
length(max(q, 0.0)) ist innerhalb des Rechtecks überall exakt null.
Folge
Eine Kantenmaske darauf färbt die ganze Fläche.
Kur
length(max(q,0.0)) + min(max(q.x,q.y), 0.0) — der Innenterm fehlt sonst.
BPublisher & Render-Check
F·05errorsubject: MZ_BODY⬡
mz-body ist Pflicht
Befund
Ohne class="mz-body" am <body> greifen Hintergrund und Grundschrift nicht.
Folge
Dunkel ist Default, hell kommt bei prefers-color-scheme: light — eine Arbeit braucht zwei Paletten.
Kur
mz-body setzen. Erzwingen mit <html data-theme="light">; darauf per MutationObserver reagieren.
F·06warnsubject: UNKNOWN_STYLE_CLASS⬡
Geratene CSS-Klassen fliegen auf
Befund
Der Publisher meldet unbekannte mz--Klassen beim Publish.
Folge
UNKNOWN_STYLE_CLASS statt gestyltem HTML.
Kur
Nur Klassen aus getCapabilities().styling. Eigene Klassen ohnemz--Präfix sind unproblematisch.
F·07behobensubject: VERBOSITY_COMPACT⬡
compact verschluckt den Render-Check nicht mehr
Befund
Bis zum Redeploy vom 2026-08-31 ließ verbosity: 'compact' Konsolenfehler und Erreichbarkeit weg — die erste Veröffentlichung lief blind.
Stand
Seither trägt compact den vollen render-Block (clean, consoleErrors, findings) und die reachability weiter; weg fallen nur Datei-Liste, libReferences und INFO-Hinweise.
Kur
Entfällt. verbosity: 'compact' darf jetzt von Anfang an gesetzt sein.
F·08errorsubject: CONSOLE_ERROR⬡
Fehler abfangen, nicht loggen
Befund
Der Ersatz greift korrekt, aber ein console.error im catch bleibt stehen.
Folge
Der Render-Check meldet CONSOLE_ERROR, obwohl die Seite sich korrekt verhält.
Kur
Init in try/catch, statischen Ersatz zeigen — und im catchnichts loggen.
F·09errorsubject: PAGE_EXCEPTION⬡
Kein throw auf Modulebene
Befund
Eine ungefangene Ausnahme im Top-Level eines ES-Moduls landet im Render-Check.
Folge
Der Render-Check meldet PAGE_EXCEPTION — auch wenn erst das 200. Bild betroffen ist.
Kur
Alles in boot(); try { boot(); } catch {}. Den Schleifenkörper ebenso.
F·10infosubject: PAYLOAD_BR⬡
Große Bündel komprimiert übergeben
Befund
publishArtifact nimmt je Datei contentBase64 mit encoding: 'br'.
Folge
40 kB Quelltext werden zu ~17 kB Base64.
Kur
br nutzen. Danach md5sum der ausgelieferten Datei gegen die lokale — die Übertragung läuft durch den Modellkontext.
F·11infosubject: MD5_HEAD_TAGS⬡
Beim md5-Abgleich die Meta-Tags einrechnen
Befund
Der Publisher schreibt canonical und die og:/twitter:-Tags beim Ausliefern in den <head>.
Folge
Die ausgelieferte index.html ist immer länger als die lokale.
Kur
Nur Begleitdateien direkt per md5sum vergleichen. Fürs HTML diff nehmen und sehen, dass nur der eingespritzte Block übrig bleibt. Oder die Injektion abschalten: metadataJson.socialPreview: false — dann ist die ausgelieferte index.html byte-gleich zur lokalen.
F·12infosubject: PATCH_MODE⬡
Zweite Datei per patch nachschieben
Befund
Ein Bundle muss nicht in einem Aufruf komplett sein.
Folge
Die MISSING_REFERENCE-Warnung des ersten Schritts ist dann erwartet.
Kur
Erst index.html publizieren, dann mit mode: 'patch' die app.js nachlegen — kein overwrite nötig, Unerwähntes bleibt.
CDer Raum, nicht das Objekt
F·13errorsubject: EMPTY_ENVIRONMENT▲
Brechung zeigt die Umgebung — nicht das Objekt
Befund
Ein Glaskörper vor schwarzem Grund sieht aus wie ein matter Stein. Völlig korrekt gerechnet, nur eben leer.
Folge
Der teuerste Irrtum bei Dispersion Cathedral — Stunden an Shader-Parametern, die nichts retten konnten.
Kur
Zuerst den Raum bauen: eine strukturierte Lichtquelle (ein Fenster mit Sprossen), deren Projektion auf dem Boden, ein zweites schwächeres Licht von der Gegenseite. Erst danach an Shader-Parametern drehen.
Was ein gebrochener Strahl beim Austritt findet, ist das Bild.
F·13 · EMPTY_ENVIRONMENT
F·14warnsubject: FLAT_AMBIENT▲
Grundlicht ist kein Ersatz für eine Quelle
Befund
Der erste Reflex ist, das Umgebungslicht hochzuziehen.
Folge
Der Raum wird flau und das Glas trotzdem nicht brillant.
Kur
Die Helligkeit muss aus einer kleinen, hellen, strukturierten Fläche kommen.
DAkkumulation & Zeit
F·15warnsubject: AUTOCLEAR◆ ●
autoClear abschalten, sobald akkumuliert wird
Befund
three löscht das Render-Target vor jedemrender().
Folge
Ein Sandbett, ein Leuchtspur- oder Kaustik-Puffer über Bilder hinweg geht genau dort verloren.
Kur
renderer.autoClear = false; neue Puffer einmal von Hand mit renderer.clear(true, false, false) räumen.
F·16infosubject: DECAY_NO_PINGPONG●
Abklingen ohne Ping-Pong
Befund
Ein Puffer lässt sich in sich selbst dimmen, ohne zweites Target.
Folge
Spart die Hälfte des Speichers und einen Kopierschritt.
Kur
Vollbild-Quad mit blendSrc: ZeroFactor, blendDst: SrcColorFactor → Ergebnis dst × srcColor, je Kanal ein eigener Abklingfaktor.
F·17warnsubject: FRICTION_PER_FRAME●
Reibung je Sekunde, nicht je Bild
Befund
v *= 0.88 verhält sich auf 30 und 144 fps völlig verschieden.
Folge
Dieselbe Arbeit ist auf dem einen Rechner zäh, auf dem anderen zappelig.
Kur
v *= pow(damp, dt * 60.0) macht die Terminalgeschwindigkeit von der Bildrate unabhängig. Erst danach Parameter suchen.
F·18errorsubject: FADE_BY_FRAME⬡
Anlaufen nach Uhrzeit, nicht nach Bildern
Befund
Ein Einblendfaktor, der pro Bild wächst, bleibt auf einem langsamen Renderer bei null.
Folge
Das Bild ist schwarz, obwohl alles läuft. Eine halbe Stunde Fehlersuche.
Kur
(now - start) / ms nehmen.
Ein Faktor, der pro Bild wächst, misst die Hardware — nicht die Zeit.
F·18 · FADE_BY_FRAME
F·19warnsubject: QUALITY_RAMP⬡
Qualitätsstufen von unten anfahren
Befund
Startet man auf der höchsten Stufe, braucht das erste Bild auf schwacher Hardware Minuten.
Folge
Die Nachregelung greift nie.
Kur
Niedrig starten, nach ~12 Bildern messen, hocharbeiten. Ein ?q=0..3, das die Stufe festnagelt, macht die Prüfung im Headless-Browser überhaupt erst möglich.
F·20warnsubject: RESEED_ON_RESTEP●
Stufenwechsel darf das Bild nicht neu würfeln
Befund
Wird bei der Nachregelung die Partikelzahl geändert, ist Neu-Streuen die naheliegende — und sichtbar falsche — Lösung.
Folge
Auf schneller Hardware fliegt das Bild in den ersten Sekunden zwei-, dreimal auseinander.
Kur
Die alte Positionstextur mit einem Resample-Pass auf das neue Raster lesen (plus Mikro-Jitter). Das alte Target erst nach dem Pass dispose().
EHeadless
F·21warnsubject: NO_WEBGL2_HEADLESS⬡
Hardware-GL gibt es im Headless hier nicht
Befund
--use-gl=egl oder --use-angle=vulkan starten zwar, liefern aber kein WebGL 2.
Folge
Die Seite fällt auf den Ersatz zurück — leicht als Bug der Arbeit missdeutet.
Kur
Nur SwiftShader. Für teure Shader kleines Fenster (800×500), niedrige Stufe, großzügiges --virtual-time-budget; ein Bild kann eine Minute Realzeit brauchen.
F·22infosubject: VIRTUAL_TIME_FROZEN⬡
Headless friert performance.now() ein
Befund
Mit --virtual-time-budget laufen Dutzende Bilder, aber die Seitenzeit wächst kaum.
Folge
Alles Zeitgesteuerte — Auto-Wechsel, FPS-Anzeige, Einblendung — lässt sich nicht prüfen; prüfbar ist nur, dass gerendert wird.
Kur
Für jeden Zustand einen URL-Parameter vorsehen und die Zustände einzeln fotografieren.
F·23infosubject: STATE_VIA_URL⬡
Jeder Zustand über einen URL-Parameter
Befund
Zeitabläufe sind headless nicht beobachtbar (siehe F·22).
Folge
Ohne Schalter bleibt ein Großteil der Arbeit ungeprüft.
Kur
?q= Stufe, ?m= Startmotiv, ?t=light|dark — je ein fester Einstieg, einzeln zu fotografieren.
§ 04
Nachsehen, ob es läuft
HTTP 200 heißt nicht, dass WebGL etwas zeichnet. Für Konsolenfehler,
unbehandelte Ausnahmen und tote Ressourcen reicht der Publisher selbst:
validateArtifact
lädt die Preview in einem echten Browser und meldet
CONSOLE_ERROR /
PAGE_EXCEPTION /
RESOURCE_FAILED
schon vor dem Publish — publishArtifact ebenso, danach.
Ein eigener Browser bleibt für den visuellen Blick auf einen teuren
Shader nötig — und für wiki--Slugs,
wo der Render-Check hinter der Zugriffssperre entfällt. Der
chrome-devtools-MCP-Server
sucht Chrome unter /opt/google/chrome/chrome
und findet auf diesem Rechner nichts — installiert ist
/usr/bin/chromium. Direkt aufrufen:
--use-angle=swiftshader plus
--enable-unsafe-swiftshader
gibt WebGL 2 in Software — langsam, aber es rendert; auf diesem Rechner der einzige Weg.
--virtual-time-budget
lässt die Simulation vor dem Screenshot ein paar Sekunden laufen, sonst fotografiert man das Startrauschen.
Im console.log ist fast alles Chrome-Eigenrauschen
(PHONE_REGISTRATION_ERROR, D-Bus,
sqlite_persistent_store, Sandbox-Warnungen).
Danach filtern, sonst übersieht man den echten Fehler.
§ 05
Die Reihe
Jeder Fallstrick oben stammt aus einer dieser drei Arbeiten. Sie laufen live.
Wyman, Sloan & Shirley, Simple Analytic Approximations to the CIE XYZ Color Matching Functions, JCGT 2 (2), 2013
Werkstattbericht zur generativen Reihe auf dem Mzone Publisher. Beschreibt den ausgelieferten
Bibliotheks-Stack, die vier Branding-Profile und dreiundzwanzig konkrete Fallstricke beim Bauen
von WebGL-Arbeiten — geordnet nach Präzision und Farbe, Publisher und Render-Check, Raum und
Objekt, Akkumulation und Zeit sowie Headless-Prüfung.