Communitygithub.com

Perspektiv-Illusion

Erstelle ein Looping-3D-Video im japanischen Perspektiv-Illusionsstil (z. B. @garments__) von beliebigen Orten wie Straßen, Kreuzungen, Bahnhöfen, Ladenzeilen, Räumen, Parks oder Dächern – eine scheinbare 2D-Zeichnung, die durch Kamerafahrten in einen tiefen 3D-Raum aufbricht.

Was ist Perspektiv-Illusion?

Dieses Skill erzeugt ein Endlos-Loop-Video im Stil einer japanischen Perspektiv-Illusion: Eine mit einer starken Telelinse aufgenommene Szene wirkt wie eine flache, gezeichnete Collage. Durch einen Dolly-Zoom (die Kamera fährt nach vorne, während die Brennweite weiter wird) öffnet sich der Raum dramatisch in die Tiefe. Gleichzeitig schwenkt die Kamera um Ecken, die zunächst flach erscheinen und dann in 3D aufklappen. Während der flachen Phasen tauschen Objekte unbemerkt ihre Positionen – aus einer geraden Reihe wird eine Diagonale. Der gesamte Look ist als saubere Line-Art mit flacher Zweiton-Schattierung, Kreuzschraffur-Schlag-Schatten und einem gemalten Himmel gehalten. Das Skill unterstützt Plattformen wie Claude Code, Cursor und Codex. Die Umsetzung erfolgt über ein npm-basiertes Build-Setup mit Three.js und Playwright. Es liefert Vorlagen für verschiedene Szenarien (Straße, Supermarkt, Nachtkreuzung) und ein detailliertes Step-by-Step-Rezept für Szenenaufbau, Kamerachoreographie, Look, Feinschliff und Rendering. Die Qualitätssicherung erfolgt durch Stichprobenbilder, einen Motion-Check und einen Blink-Detektor. Die Anleitung ist so umfangreich, dass selbst komplexe Illusionen mit diesem Skill systematisch produziert werden können.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/wsxiaolin/perspective-illusion/tree/main

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Was macht Perspektiv-Illusion?

Der Stil in einem Absatz

Eine waagrecht ausgerichtete Kamera mit einem sehr langen Objektiv (ca. 2° Gesichtsfeld aus 400 m Entfernung) drückt eine tiefe Szene flach – sie sieht aus wie eine gezeichnete Collage. Dann vollführt sie einen Dolly-Zoom: Das Objektiv wird weiter, während die Kamera nach vorne fährt, sodass das Motiv gleich groß bleibt, aber der Raum dahinter sich aufdehnt. Die Kamera schwenkt auch um Ecken. Jede dieser Einstellungen beginnt flach und öffnet sich in 3D. Während der flachen Ansicht tauschen Objekte unbemerkt ihre Tiefe – sobald die Tiefe zurückkommt, ist aus einer geraden Reihe eine Diagonale geworden. Alles ist als saubere Tusche-Line-Art mit flacher Zweiton-Schattierung, schraffierten Schlagschatten und einem gemalten Himmel gezeichnet, und das Ganze loopt nahtlos.

Schnellstart

mkdir -p ~/Movies/edits/<datum>-<name>/stills && cd $_
printf '{"type":"module"}' > package.json && npm i [email protected] [email protected]
cp -r ~/simcraft/skills/video/perspective-illusion/templates/* .
cp scramble_night.html scene.html                                # oder die nächstgelegene Vorlage (siehe unten), dann editieren
node render.mjs scene.html x --stills=0.3,1.5,3,6,8.5           # Einzelbilder jeder Einstellung, in stills/
node render_fast.mjs scene.html preview.mp4 --preview            # gesamter Loop, halbe Größe, ca. 1,5 Min.
node render_fast.mjs scene.html final.mp4                        # volle Qualität, ca. 30 Min. für 10 s
python3 ~/simcraft/skills/video/vox-explainer/scripts/motion_check.py final.mp4
python3 ~/simcraft/skills/video/perspective-illusion/scripts/blink_map.py ffmpeg final.mp4 blink.png

Behebe Probleme an Einzelbildern und Vorschauen. Die vollständige Render-Ausführung starte erst, wenn die Vorschau freigegeben ist. Setze $FFMPEG, falls ffmpeg nicht im PATH ist.

Vorlagen

Starte mit der Vorlage, die der neuen Szene am nächsten kommt. Behalte ihr Kamerarig, die Timeline, den Post-Pass und die Render-Hooks bei, und ersetze nur den Szenenabschnitt (alles zwischen // ---------- kit und // ---------- cameras).

VorlageSzeneRenderer
street.html, street_plus.htmlTagstraße mit Masten, Kegeln, einem Zebrastreifen und rotem Himmel. street_plus fügt Details und Eckansichten hinzu.render_smooth.mjs
market.html, market_real.htmlSupermarktgang, gezeichnet und realistisch.render_smooth.mjs (market.html: render.mjs)
scramble_night.htmlGroße Kreuzung bei Nacht mit Regen, Menschenmenge, nassen Reflexionen und Werbetafeln. Enthält alle Beschleunigungen.render_fast.mjs

Für eine neue Szene ist scramble_night.html die beste Basis für die Engine, da es als einziges die Hooks für den schnellen Renderer hat. Entferne ihre Nacht-Extras (siehe reference.md) für einen Tageslook.

Schritt 1: Eine Szene bauen, die das Auge täuscht

Jeder Ort funktioniert, wenn er Folgendes hat:

  • Eine lange Achse. Richte die Szene entlang -z aus (eine Straße, ein Gang, ein Bahnsteig, ein Korridor), mit der Kamera, die darauf blickt. Die Tiefe entlang dieser Achse wird durch das Tele versteckt.
  • Wiederholte Dinge in verschiedenen Tiefen. Masten, Lampen, Regale, Säulen, Schilder, Bäume, Menschen. Bei langer Brennweite stapeln sie sich zu einer Ebene. In einer Linie aufgestellte Masten verschmelzen zu einem, und Schildstapel an fernen Fassaden türmen sich zu einer Wand auf.
  • Tausch-Objekte. 3 bis 6 ähnliche Objekte (Kegel, Menschen, Mülltonnen, Stühle, Kisten), deren Anordnung zwischen einer Reihe und einer Diagonale wechselt. Sie können in der flachen Ansicht (cs) auch größer gezeichnet werden, sodass der Maßstab im flachen Zustand stimmt.
  • Realwelt-Maßstäbe in Metern. Die Objektive und Fokusebenen funktionieren nur bei echten Maßstäben: ein 0,75 m hoher Kegel, 1,7 m große Menschen, eine 3,2 m hohe Etage.
  • Details dort, wo die Eckansichten hinschauen. Jede Eckansicht zeigt Gebäudeseiten, Rückseiten von Objekten und den Boden. Fülle sie: Seitenfenster, Abflüsse, Kabel, Bordsteine, den Berührungsschatten unter einem Auto. Flache Ansichten verzeihen Schlamperei, Eckansichten decken sie auf.
  • Jedes Detail muss entweder Teil einer Oberfläche sein (Texturen, gestapelte Hüllen) oder mindestens 0,4 m Abstand zu anderen Oberflächen haben. Aus 400 m Entfernung flimmern Oberflächen, die nur wenige Zentimeter auseinanderliegen.

Schritt 2: Kamera-Choreografie

Die Kamera wird niemals geneigt. Sie bleibt waagrecht, sodass Vertikalen vertikal bleiben – wie in einer Architektenzeichnung. Jede Einstellung ist ein einfaches Objekt:

{ x, y, zf, W, fov, H, el, yaw, lay, cs }

SchlüsselBedeutung
x, ySeitliche Position und Höhe der Kamera (m)
zf, WDie Fokusebene und die dort eingefasste Breite (m). Wenn man W beibehält und fov ändert, erhält man den Dolly-Zoom.
fovHorizontaler Öffnungswinkel. Ca. 2° ergibt flach, 25–90° erzeugt Tiefe.
HLens-Shift: Wo der Horizont liegt (-1 unten, 0 Mitte, 1 oben).
elBlick nach unten durch Anheben der Kamera und Verschieben des Objektivs, niemals durch Neigen.
yawSchwenken um den Fokuspunkt – für Eckansichten.
lay, csAnordnung der Tausch-Objekte (0 Reihe, 1 Diagonale) und ihr Maßstab in der flachen Ansicht.

Bewährtes Einstellungs-Vokabular:

EinstellungEinstellungen
Flachfov ca. 2, H 0. Die gesamte Szene wirkt wie ein Aufriss.
FroschperspektiveKnöchelhöhe, fov 90, Horizont tief (H ca. -0.7).
HochKamera hoch oben bei mittlerer Brennweite, Horizont über dem Bildrand.
Eckansichtyaw ±18 bis 35°, el 9 bis 50°. Kommt als Paar: zuerst eine Tele-Version (fov 4), dann die gleiche Ansicht weit (fov 25 bis 45).
Diagonal und niedrigMittlere Brennweiten, die die Tausch-Objekte in der Tiefe zeigen.

Loop-Struktur. Flach, dann eine tiefe Ansicht, dann eine Eckansicht (flach dann 3D), zurück zu flach (hier die Objekte tauschen), eine hohe Diagonale, die andere Eckansicht, eine niedrige Einstellung, dann wieder flach. Der Loop endet auf der gleichen Einstellung, mit der er beginnt.

Timing. Alle Parameter durchlaufen eine monotone kubische (Fritsch-Carlson) Kurve über die Key-Zeiten, sodass die Geschwindigkeit nie springt. Interpoliere W und fov im logarithmischen Raum. Füge winzige „Drift“-Einstellungen hinzu (W × 0.96), damit Haltepunkte atmen, statt einzufrieren. 10 s fühlen sich flüssig an, 7 s wirken gehetzt. Um die Länge zu ändern, skaliere die Key-Zeiten statt sie neu zu schreiben.

Schummeln während der flachen Phasen. Ändere lay nur während flacher Halte. Wenn sich die Kamera in der Tiefe bewegt, während sich Objekte bewegen, wird der Trick sichtbar.

Die erste Eckansicht sollte auf die Seite gehen, die das Helden-Objekt (ein Auto, ein Schild) nicht verdeckt. So zeigt die Enthüllung etwas Neues.

Schritt 3: Der Look

Die Seite rendert vier Durchgänge: Farbe, Normalen mit Tiefe, Flachfarbe (ohne Beleuchtung) und eine Sonnen-nur-Schattenmaske. Ein finaler Shader kombiniert sie.

  • Tuschel-Linien dort, wo sich Tiefe (zweite Differenz), Normalen oder Flachfarbe ändern. Mache Linien in der Nähe schwerer. Bodenmarkierungen erhalten dünne graue Linien. Lasse Farblinien ausblenden, wo ein Pixel viele Meter abdeckt oder ferne Texturen zu Rauschen werden.
  • Zweiton-Schattierung. Hell gegen Schatten, ohne Abstufungen. Setze die Maskenlichtquelle auf 2*PI, weil drei.js den Lambert durch pi teilt – ohne wird alles zu Schatten.
  • Schraffiere nur Schlagschatten, mit weltraumverankerter (niemals bildschirmraum-basierter) Schraffur und ausgeblendet durch fwidth.
  • Malen den Himmel nach Blickrichtung, nicht nach Bildschirmposition, damit Wolken beim Kamerafahren stehen bleiben. Halte Wolkenkanten weich.
  • Palette. 6 bis 10 flache Farben plus eine Akzentfarbe (ein roter Himmel, ein gelbes Schild). Um eine Referenz zu treffen, nimm die Farben aus ihren Bildern mit k-Means.
  • Licht. Eine einzige, tief stehende, harte Sonne, so platziert, dass die Hauptmotive beleuchtet bleiben und lange Schatten über den Boden werfen. Eine Sonne von der hohen Seite begräbt die Szene in einem großen Schatten.

Für eine Nacht-Variante (Mondlicht, beleuchtete Fenster, nasse Reflexionen, Glühen, Regen, Grading), eine Menschenmenge oder Werbetafeln und Leuchtschriften siehe reference.md.

Um aus scramble_night.html einen Tageslook zu erhalten:

  • Ersetze den Mond durch eine warme Sonne und erhöhe das Umgebungslicht.
  • Entferne die Punktlicht-Schleife.
  • Entferne den nassen-Boden-Block, die Dunstlinie und das Nacht-Grading aus dem Post-Shader.
  • Entferne den Regen und setze emissiveIntensity bei Fenstern auf 0.
  • Setze einen Taghimmel skyAt.

Schritt 4: Detail-Durchgänge (was es großartig macht)

Erste Versionen wirken immer leer. Großartige Versionen entstehen durch gezielte Durchgänge, die jeweils an Einzelbildern geprüft werden, bevor der nächste beginnt.

  1. Formen. Hauptmassen im echten Maßstab, die lange Achse, die Tausch-Objekte und die Kamera-Timeline. Prüfe, dass die flache Einstellung wirklich flach wirkt und jede Bewegung etwas offenbart.
  2. Struktur. Alles, was ein realer Ort hat, aufgebaut aus realweltlicher Logik. Für eine Straße bedeutet das: Bordsteine, Abflüsse, Kanaldeckel, Masten mit ihren Armen und Kästen, Schilder auf beiden Seiten, Zäune, Mülltonnen, Getränkeautomaten, Fahrradständer, Oberleitungen, Fensterrahmen mit Fensterbänken und Klimaanlagen. Sieh dir Fotos der echten Art von Ort an und liste auf, was dort vorhanden ist, bevor du baust.
  3. Abnutzung und Geschichte. Kleine Dinge, die bewohnt wirken lassen: Aufkleber, Klebeband, Plakate mit codiertem Text, Pfützenflecken, ein angelehntes Fahrrad, Wäsche, eine Katze, eine Kaffeetasse. Strebe 3 oder mehr pro Oberfläche an, auf der die Kamera verweilt.
  4. Eckansichten-Prüfung. Rendere für jede Eckansicht das weite Standbild und fülle, was dort kahl wirkt. Meistens sind das Gebäudeseiten, die Rückseiten von Schildern, Dächer (Tanks, Geländer, Antennen) und der Boden zwischen Objekten.
  5. Licht und Schatten. Stelle sicher, dass jedes Objekt einen lesbaren Schatten wirft, füge Berührungsschatten unter geparkten Dingen hinzu und bekomme die Schattenseite jeder Hauptform in den Zweiton-Schritt. Schatten, die nur in einer Ansicht auftauchen, sind eine Belohnung für die Kamerafahrt.
  6. Leben (optional) . Gehende Personen, ein Zug oder Autos mit konstanter Geschwindigkeit, Bildschirme, Vögel, Fahnen. Alles loopt eine ganze Anzahl von Malen.
  7. Feinschliff. Palettenharmonie, Linienstärke, Himmel, Vignette und Grading. Dann die Blink-Prüfung am Finalen.

Dichteregel: Aus der flachen Tele-Einstellung sollte das Bild von Rand zu Rand voll wirken, wie eine dichte Illustration, ohne große leere Wand- oder Bodenfläche, es sei denn, sie dient als bewusste Ruhepause für das Auge.

Die Qualitätslatte

Prüfe vor jedem vollständigen Render Einzelbilder zu jedem Key-Zeitpunkt (und auf halbem Weg zwischen Bewegungen) anhand dieser Liste. Behebe alles, was nicht besteht, und prüfe dann erneut.

  • Die flache Einstellung wirkt als flache Zeichnung. Nichts verrät die Tiefe.
  • Jede Bewegung endet mit einer Enthüllung: einer versteckten Diagonale, einer Seitenstraße, Objekten, die weit auseinander lagen.
  • Eckansichten beginnen flach und öffnen sich, und die erste wendet sich vom Helden-Objekt ab.
  • Linien sind scharf und gleichmäßig, keine Doppellinien, keine Tusche auf leuchtenden Flächen, kein Rauschen auf fernen Texturen.
  • Zweiton-Schattierung ist deutlich auf jeder Hauptform, und Schraffur erscheint nur in Schlagschatten.
  • Nichts wirkt wie ein nackter Grundkörper. Jeder Kasten hat Verkleidung, Nähte, einen Sockel oder eine Beschriftung.
  • Text ist lesbar und richtig geschrieben, in echten Schriften, mit erfundenen Marken.
  • Der Himmel passt zur Lichtrichtung und -farbe der Szene.
  • Die Palette ist begrenzt und harmonisch, mit einem klaren Akzent.
  • Die Loop-Naht ist unsichtbar (Frame 0 gleich letztem Frame), und nichts springt.
  • Die Vorschau hat kein Ruckeln. Im Finale ist die blink_map-Zahl niedrig, und was blinkt, ist beabsichtigte Bewegung (Regen, Bildschirme).

Wenn du Einzelbilder überprüfst, betrachte sie wie ein Illustrator: Benenne die drei schwächsten Bereiche jedes Bildes, behebe sie und wiederhole. Höre nicht bei „es funktioniert“ auf.

Schritt 5: Rendern und prüfen

  • render_fast.mjs rendert jedes Bild auf der GPU als Mittelwert mehrerer verrauschter Unter-Renderings: 4 für Anti-Aliasing und bis zu 32 bei schnellen Bewegungen für lückenlose Bewegungsunschärfe, dimensioniert danach, wie weit sich window.probe-Punkte auf dem Bildschirm bewegen. Verwende --preview für halbe Größe bei 30 fps. --from, --to und --fps sind ebenfalls verfügbar.
  • render_smooth.mjs liefert die gleiche Qualität für Seiten ohne renderMany, mittelt aber in ffmpeg, daher mehrere Male langsamer.
  • Statische Meshes nach Material zusammenführen (BufferGeometryUtils.mergeGeometries). Eine Szene ging von 7.654 Draw-Calls auf 530, etwa 7× schneller. Alles, was sich bewegt, von der Zusammenführung ausnehmen.
  • Das Finale prüfen mit motion_check.py (nichts friert ein) und blink_map.py, das Pixel zählt, die in nahezu unbewegten Bildern flackern. Vergleiche den Wert vor und nach einer Änderung. Vorschauen schimmern konstruktionsbedingt – beurteile Blinken nur im Finalen.

Der Seitenvertrag

Jede Szenenseite funktioniert mit den Renderern, wenn sie Folgendes bereitstellt:

HookFunktion
#frameDie Canvas, die screenshottet wird.
window.READYGesetzt, sobald Assets und Schriften geladen sind.
window.render(ms)Zeichnet den Frame zur Zeit ms.
window.probe(ms)Gibt Bildschirmpositionen einiger Weltpunkte zurück, verwendet zur Dimensionierung der Bewegungsunschärfe.
window.setJitter(x, y)Subpixel-Linsenversatz in Pixeln, gesetzt über projectionMatrix.elements[8] und [9].
window.renderMany([[ms, jx, jy], ...])Mittelt mehrere Renderings in einem Aufruf (erforderlich für render_fast).
?scale=.5Rendert bei halber Größe.

Alles Animierte muss eine reine Funktion von ms sein, periodisch in der Loop-Länge. Verwende ganze Zahlen von Zyklen pro Loop für Schritte, Krabbelbewegungen und Regen.

Blinken und Störungen

UrsacheBehebung
Alles im Bildschirmraum (Wackeln, Schraffur, Rauschen, Dunst nach Kameradistanz)Verankere es an der Welt oder an der Blickrichtung.
Oberflächen wenige cm auseinanderFasse sie zu einer Oberfläche zusammen oder halte sie mindestens 0,4 m auseinander.
Überlappende koplanare Ebenen (Fahrbahnmarkierungen, Bodenplatten)Male Markierungen auf eine Ebene und lasse Platten Kante an Kante treffen.
Subpixel-Details (Schienen, Gitter, Kabel, Regen)Jitter-Anti-Aliasing auf jedem Frame und blasse dichte Linien nach Metern pro Pixel ausblenden.
Ein Render pro FrameNiemals im Finalen tun.
Harte Kanten an Wolken oder ReflexionenWeichzeichnen und Effekte an Bildrändern ausblenden.
Bewegte Dinge, die wickeln oder springenWickel sie während der schnellsten Kamerabewegung des Loops, ermittelt mit window.probe.

Fallstricke

  • Ein //-Kommentar, der zu einzeiligem Code hinzugefügt wird, verschluckt den Rest der Zeile (ein scene.add, ein Licht). Verwende /* */.
  • Helfer, die zur Szenenwurzel hinzufügen (wie plane()), ignorieren die aktuelle Gruppe und können oben auf Dingen landen. Baue innerhalb von Gruppen.
  • Halte emissive Flächen (Bildschirme, Schildtafeln) aus dem Flachfarb- und Schattendurchgang heraus, sonst werden alle Zeichen eingetuscht und abgedunkelt.
  • ffmpeg -stream_loop ... -c copy erzeugt Schleifen, die einige Player früh beenden. Stattdessen neu encodieren.
  • Für X sind Side-by-Sides bei 32:9 zu breit zum Hochladen. Staple sie vertikal.
  • Verwende nur Originalcharaktere und erfundene Marken. Kopiere die Technik einer Referenz, niemals ihr Kunstwerk.

Verwandte Skills