Animationsfilm in 8 kB
(ctrl-alt-test.fr)- Das Team Ctrl-Alt-Test begann im November 2022 mit einem Experiment, eine Echtzeit-Demo, die wie ein animierter Kurzfilm aussieht, in 8 kB unterzubringen, und veröffentlichte im April 2023 The Sheep and the Flower
- Das Ergebnis ist eine einzelne
.exe, die Grafik und Musik ohne Ressourcendateien oder externe Abhängigkeiten erzeugt; die Szenen werden per GLSL-Shader und Raymarching in Echtzeit auf der GPU berechnet - Schaf, Schild, Kamera und Timeline bestehen nicht aus gespeicherten Modellen oder Texturen, sondern aus SDFs, prozeduralen 3D-Texturen und hartkodierten Zeitparametern; rund 25 Kamerashots wurden manuell abgestimmt
- Die Musik wurde mit OpenMPT und 4klang erstellt; für eine bessere Kompression wurde die Zahl der Instrumente von 16 auf 13 reduziert und mehr Wiederholung eingebaut
- Die finalen 8 kB wurden durch Crinkler-Kompression und Verbesserungen an Shader Minifier möglich; 42 kB Shader-Code passen nach Minifizierung und Kompression in etwa 5 kB und lassen Platz für Musik und C++-Code
Eine einzelne ausführbare Datei in 8 kB
- The Sheep and the Flower ist eine Echtzeit-Animation in Form einer Windows-Executable, veröffentlicht im April 2023
- Eine einzige
.exeerzeugt alles, ohne separate Ressourcendateien oder externe Abhängigkeiten- Für die Ausführung werden Windows und aktuelle Treiber benötigt
- Das Ziel war, Grafik, Animation, Inszenierung, Kameraführung und Musik komplett in 8 kB unterzubringen
- Der Quellcode ist auf GitHub veröffentlicht: ctrl-alt-test/mouton
Werkzeuge für Grafik, Musik und Kompression
- Alle visuellen Elemente werden in Echtzeit auf der GPU berechnet
- Die GLSL-Shader enthalten Timeline-Informationen, Kameraeinstellungen und sogar die Szenenbeschreibung
- Das Rendering erfolgt per Raymarching
- Die Shader wurden mit Shader Minifier verkleinert
- Die Musik wurde mit OpenMPT und dem Synthesizer 4klang erstellt
- Die Instrumente sind prozedural beschrieben
- Die Notenlisten werden komprimiert
- Der Code wurde in C++ mit Visual Studio 2022 geschrieben
- Compiler-Flags und Initialisierung basierten anfangs auf dem Framework Leviathan
- Die finale Executable wurde mit Crinkler komprimiert
Warum 8 kB?
- In der Demoszene sind Kategorien mit Größenlimits wie 4 kB und 64 kB üblich
- Frühere Arbeiten zielten meist auf 64 kB, aber 8 kB bringen ganz andere Einschränkungen und Regeln mit sich
- Techniken für 4-kB-Intros sind spannend, wurden für echtes Storytelling aber als zu begrenzt angesehen
- Da die Revision demoparty vor einigen Jahren einen 8-kB-Wettbewerb hinzugefügt hatte, bot sich das als gute Gelegenheit für ein Experiment an
Eine Welt aus zwei Dreiecken
- Wie in der Demoszene seit 2008 üblich, wird ein das gesamte Bild abdeckendes Rechteck aus zwei Dreiecken gezeichnet
- Auf diesem Rechteck berechnet ein GLSL-Shader für jedes Pixel und jedes Frame die Farbe
- Die Shader-Funktion nimmt Koordinaten und Zeit als Eingabe und gibt eine Farbe zurück
- Die Kernfrage war, wie sich innerhalb dieser Funktion das Schaf und die ganze Szene darstellen lassen
Aufbau der Szene mit SDFs
- Eine Signed Distance Field (SDF) ist eine Funktion, die für einen Punkt im Raum den Abstand zum nächstgelegenen Objekt berechnet
- Auf der Oberfläche gibt sie 0 zurück
- Im Inneren eines Objekts liefert sie negative Werte
- Grundformen wie Kugeln oder Boxen lassen sich mit einfachen Formeln beschreiben
- Durch Kombination mehrerer Distanzfelder entsteht die Szene
- Die Vereinigung zweier Objekte lässt sich über das Minimum der Distanzen bilden
- Der Schnitt über das Maximum
- Mit einer glatten Vereinigung (smooth union) entstehen organischere Formen
- Das Schaf wurde durch Zusammenbau und Verschmelzung einfacher Formen wie Kegel und Kugeln erzeugt; Körper und Wolle basieren auf 3D-Rauschfunktionen
Wie Raymarching die Pixel bestimmt
- Raymarching ist eine Rendering-Technik, bei der mit Hilfe von SDFs ein Strahl schrittweise durch eine 3D-Szene bewegt wird
- Anders als beim klassischen Raytracing werden Schnittpunkte nicht direkt mathematisch berechnet
- Die SDF gibt an, wie weit sich der Strahl gefahrlos bewegen kann, und genau um diese Distanz wird er wiederholt vorgerückt
- Wenn die Distanz 0 oder nahezu 0 wird, gilt der Schnittpunkt als gefunden
- Sobald ein Schnittpunkt entsteht, lässt sich bestimmen, ob das aktuelle Pixel zum Schaf, zum Himmel oder zu einem anderen Objekt gehört
- Für die Beleuchtung werden Oberflächennormalen benötigt, die über lokale Gradienten angenähert werden
- Schatten werden berechnet, indem vom Schnittpunkt ein weiterer Strahl in Richtung Sonne gesendet wird, um zu prüfen, ob unterwegs ein Objekt liegt
Wie man mit wenig Ausdrucksmitteln eine Geschichte erzählt
- Die Demo enthält weder Sprache noch Text und hat nur eine Figur
- Das Schaf kann im Wesentlichen nur laufen und Kopf sowie Augen bewegen; drehen kann es sich nicht
- Um innerhalb dieser Grenzen Emotionen zu vermitteln, wurden irrelevante Elemente entfernt
- Anfangs dachte das Team an eine Wüste mit Dünen und Himmel, hielt das für die Geschichte aber nicht für nötig
- Der Hintergrund blieb reinweiß
- Texturen wurden reduziert, abgesehen von Schild und Augen, die Bedeutung transportieren
- Der kleine Umfang half dabei, sich auf Details, Polishing, Kameraführung, Schnitt und Musiksynchronisation zu konzentrieren
- Jeder Shot wurde manuell gebaut, und die Animation wurde wiederholt angepasst, bis sich der Ablauf natürlich anfühlte
Kamera und Inszenierung
- Die Kamera wurde als Werkzeug des Erzählens eingesetzt
- Für Szenen, in denen das Schaf lange umherirrt, wurden weite Einstellungen verwendet, um Einsamkeit zu vermitteln
- In dem Moment, in dem es das Schild bemerkt, kommt eine Extreme-Close-up-Aufnahme des Auges zum Einsatz
- Wenn das Schaf auf das Schild blickt, wird langsam in Richtung Kopf gezoomt, um den Fokus zu verstärken
- Die Aufregung des Schafs wird durch mehrere überlagerte Mittel vermittelt
- comicartige 2D-Effekte
- schnelleres Gehen
- betonte Schwanzbewegungen
- übertriebenes Kopfschütteln
- ein dramatischer Wechsel in der Musik
Entwicklungsweise für schnelle Iteration
- Der Quellcode enthält viele hartkodierte Konstanten
- Größe der Schafsaugen
- Geschwindigkeit der Kamerabewegung
- Länge einzelner Shots
- Werte wie die Farbe der Blume wurden immer wieder angepasst
- Für schnelles Feedback wurden Shader zur Laufzeit neu kompiliert, sodass die Grafik in unter einer Sekunde aktualisiert wurde
- Für Animation und Kamerafeinabstimmung war ein Player nötig
- Pause
- Wiedergabe
- Zeitsteuerung
- sofortige Kontrolle nach Live-Reload des Shaders
- Um Musik und Animation exakt zu synchronisieren, war Musikunterstützung ebenfalls unverzichtbar
- Erste Prototypen entstanden in Shadertoy, gingen dann über KodeLife in ein C++-Projekt über
Mit 4klang erzeugte Musik
- Die Musik war ein zentrales Element für das Erzählen und musste verschiedene Stimmungen sowie bestimmte Wendepunkte tragen
- Verwendet wurden dieselben Werkzeuge wie für 4-kB-Intros, mit mehr Platz für komplexere Strukturen
- Der 4klang synthesizer bietet ein Plugin zur Nutzung in Musiksoftware und exportiert Assembler-Dateien
- Diese Assembler-Datei wird zusammen mit der Demo kompiliert und gelinkt
- Beim Start der Demo erzeugt der Synthesizer in einem separaten Thread prozedural Wellenformen und sendet sie an die Soundkarte
- Die zuerst komponierte Musik war größer als erwartet und wurde mehrfach angepasst, um Platz zu sparen
- Die Zahl der Instrumente wurde von 16 auf 13 reduziert
- Das Ending-Thema wurde passend zum Gesamttempo der Musik neu komponiert
- Mehr Wiederholung wurde eingebaut, damit die Kompression besser greift
- Änderungen, die akustisch kaum auffallen, etwa bei der Notenlänge von Hintergrundstimmen, verbesserten die Kompressionsrate
- So blieb die Gesamtstruktur der Musik erhalten, während Qualitätsverluste minimiert und Speicherplatz gespart wurden
Animation und Zeitsynchronisierung
- Die Demo wertet in jedem Frame alles neu aus, ohne Vorberechnung oder Cache
- Das ist ungünstig für die Performance, aber gut für Animationen, weil sich jedes Element zeitabhängig verändern kann
- Die komplette Demo besteht aus etwa 25 manuell erstellten Kamerashots
- Jeder Shot beschreibt, wie sich 18 Parameter im Zeitverlauf ändern
- Position jedes Objekts
- Zustand des Schafs
- Kameraposition
- Fokus
- Zielpunkt der Kamera und mehr
- Als Beispiel beschreibt schon eine Zeile wie
camPos = vec3(22., 2., time*0.6-10.);die lineare Kamerafahrt eines Shots timebedeutet nicht die absolute Zeit seit Start der Demo, sondern die Zeit seit Beginn des jeweiligen Shots- Dadurch lassen sich Shots einfügen, löschen oder anpassen, ohne den Rest der Demo stark zu beeinflussen
- Da einfache lineare Interpolation mechanisch wirken kann, wurde in vielen Fällen smoothstep verwendet
- Der Timeline-Code befindet sich im Vertex Shader
- Die Shot-Definitionen enthalten viel Wiederholung, was der Kompression jedoch zugutekommt
Texturen und Materialien
- In klassischen Renderern werden 2D-Texturen auf die Oberfläche eines 3D-Modells gelegt
- Beim Raymarching sind Texturkoordinaten schwer direkt zu berechnen, daher werden stattdessen 3D-Texturen on the fly berechnet
- Sobald der Raymarcher die 3D-Position für das Rendering gefunden hat, wird genau diese Koordinate an eine Texturfunktion übergeben
- Verkehrsschilder werden mathematisch aus Dreiecks- oder Rechteckrahmen aufgebaut; der Inhalt im Inneren entsteht durch Kombination mehrerer Funktionen
- Das Restaurantsymbol besteht aus vier schwarzen ovalen Formen und zwei weißen Formen, die Aussparungen erzeugen
- Für mehr visuelle Vielfalt wurden nicht nur Texturen, sondern auch Materialien unterschiedlich gestaltet
- So erhielten etwa die Hufe des Schafs über den Fresnel-Koeffizienten ein anderes Reflexionsverhalten
Künstliche Spiegelungen für lebendige Augen
- Während der Entwicklung wirkten die Augen lange leblos und flach
- Dabei waren die Augen zentral für Charakterdesign und Storytelling
- Referenzbilder von Comicfiguren zeigten: Viele haben eine Iris, nötig ist sie aber nicht; die Pupillen sind fast immer groß gezeichnet
- Für funkelnde Augen brauchte es Lichtreflexe im Auge
- Mit der normalen Beleuchtungsgleichung entstanden diese Reflexe nur, wenn Sonne und Kamera in ganz bestimmten Positionen standen
- Um das zu verbessern, wurde der Oberflächennormalenvektor verändert, damit Sonnenreflexe wahrscheinlicher auftreten
- Zusätzlich kam Environment Mapping zum Einsatz
- In Spielen dient das normalerweise dazu, reale Umgebungsreflexionen vereinfacht und effizient darzustellen
- Hier ist die eigentliche Welt fast vollständig weiß, aber per Textur wurden künstlich Details ergänzt
- Das Augenweiß und die Pupillen enthalten deutlich komplexere Reflexionen als die leere Welt selbst
- mehrere künstliche Lichtquellen
- ein Verlauf, der dunklen Boden und blauen Himmel imitiert
Post-Processing und visueller Stil
- Die endgültige Stimmung und Bildqualität wurden im Post-Processing verfeinert
- Zum Einsatz kamen
- Color Grading
- Gammakorrektur
- leichte Vignettierung
- ein zweistufiger FXAA-Filter zur Reduktion von Aliasing
- Manche Effekte, etwa der Sterneffekt in den Augen oder der Effekt im Ending-Screen, wurden ebenfalls im Post-Processing umgesetzt
- Diese Effekte sind rein 2D und existieren nicht in der 3D-Welt
- Zeitweise wurde auch mit einem stilisierten Look wie in alten Cartoons experimentiert
- Konturenerkennung für einen handgezeichneten Eindruck
- Schwarzweiß-Rendering
- Grain und Rauschen
- Nach Diskussionen wurde dieser Ansatz verworfen und stattdessen auf einen saubereren, moderneren Look gesetzt
Crinkler-Kompression
- Die Grundidee lautet, keine Daten zu speichern, sondern Code, der die Daten erzeugt
- Bei der Musik werden die Listen zu spielender Noten und die Befehlslisten der einzelnen Instrumente gespeichert
- Crinkler ist ein Kompressionswerkzeug, das für die Demoszene und Intros von 1 kB bis 8 kB entwickelt wurde
- Da die Executable sich selbst entpacken können muss, enthält Crinkler kleinen Assembler-Code, der den Rest der Datei dekomprimiert
- Crinkler priorisiert Größenoptimierung
- Der Kompressionsalgorithmus braucht Zeit
- Das Entpacken ist vergleichsweise langsam
- Es werden mehrere hundert MB RAM verwendet
- Doch Crinkler allein reichte nicht aus; um 42 kB Shader-Quellcode in die Executable zu bekommen, war zusätzliche Verkleinerung nötig
Verbesserungen an Shader Minifier
- Da der Shader-Quellcode in das finale Binary eingebettet wird, muss er so klein wie möglich sein
- Man könnte das händisch machen, aber das erschwert Wartung und schnelle Iteration
- Shader Minifier ist ein seit 2011 entwickeltes Werkzeug zur Verkleinerung von Shadern
- Es entfernt Leerraum und Kommentare, kürzt Variablennamen und führt weitere Transformationen aus
- 8-kB-Intros enthalten viel mehr Code als 4-kB-Intros, wodurch neue Probleme entstanden; um die nötigen Funktionen zu ergänzen, wurde die Demoarbeit einen Monat lang pausiert
- Für gute Minifizierung war nicht bloß ein einfacher Minifier nötig, sondern ein Source-to-Source-Compiler ähnlich dem Closure Compiler
- Zu den Transformationen von Shader Minifier gehören
- Umbenennen von Variablen und Funktionen
- Inlining von Variablen
- Auswertung konstanter arithmetischer Ausdrücke
- Inlining von Funktionen
- Entfernen toten Codes
- Zusammenführen von Deklarationen
- Es reicht nicht, nur die Codegröße selbst zu verkleinern; das Ergebnis muss auch kompressionsfreundlich sein
- Manche Transformationen verkleinern den Code, können aber die Größe nach der Kompression erhöhen
- Während der Entwicklung musste daher die komprimierte Größe ständig überprüft werden
- Die neuen Verbesserungen an Shader Minifier sparten im komprimierten Binary rund 600 Byte
- Am Ende passten 42 kB Shader-Code nach Minifizierung und Kompression in etwa 5 kB
- Der verbleibende Platz ging an Musik und C++-Code
Ein Ergebnis, das auf der Arbeit anderer aufbaut
- Diese Demo entstand auf Basis der Arbeit anderer an Raymarching-Techniken, Musikgenerierungssoftware, Kompressionsalgorithmen und mehr
- Es bleibt die Hoffnung, dass die neuen Funktionen in Shader Minifier künftig beim Bau noch besserer Demos helfen
- Die 8-kB-Kategorie bietet mehr Möglichkeiten als 4 kB und soll hoffentlich noch populärer werden
- Zum Vergleich: Der Originaltext umfasst etwa 21.000 Zeichen und würde unverändert rund 21 kB benötigen
1 Kommentare
Hacker-News-Meinungen
Ich bin der Macher des Originalfilms, von dem dieser Film inspiriert wurde: https://www.youtube.com/watch?v=khWXdkryBE4
Beim Original liegen allein Blender, SVG und Audiodateien schon im MB-Bereich; dass das Remake in 8 kB passt, ist wirklich beeindruckend.
Schön zu sehen, dass eine Creative-Commons-Lizenz tatsächlich nützlich war; allerdings hätte ich es noch besser gefunden, wenn derselbe Igel-Charakter und dieselbe Audiomelodie verwendet worden wären.
Sloot lebt!!!
https://en.m.wikipedia.org/wiki/Sloot_Digital_Coding_System
Man sammelt einen Haufen Demoscener ein, zeigt ihnen den Film und sperrt sie für eine Weile in einen Raum mit Computern.
Mit großer Leinwand, großer Soundanlage, Bier und Junkfood funktioniert es noch besser; danach nimmt man einfach die fertige ausführbare Datei entgegen.
aEin aus Performance-Gründen in Rust geschriebener Interpreter wertet den Befehl
aaus und schreibt dabei zur Laufzeit eine bestimmte, eingebettete Payload nach STDOUT.Wirklich ein verdammt großes Pech für alle Beteiligten.
Sie haben vermutlich nicht verstanden, dass es sich a) um eine Einwegfunktion handelt und b) selbst wenn sie nicht einwegig wäre, mehrere Eingaben auf denselben Hash abgebildet werden können.
Demoscene-Videos sind ziemlich interessant, aber absurd wenig bekannt.
https://www.youtube.com/playlist?list=PLRQwR4-_0PR9HBI_GZs1nTn7q5LTkGeCN
Ich wünschte, es gäbe einen Kanal, der das Innenleben mit guten Visualisierungen erklärt, ähnlich wie retro game mechanics.
Als es noch keine Videos gab, musste man ziemlich lange auf das Entpacken und Verarbeiten warten, bevor man beeindruckt oder enttäuscht sein konnte.
Früher habe ich in den Pausen viele Demos angeschaut; sie waren der perfekte Hintergrund für meine damalige Geistesverfassung.
https://en.wikipedia.org/wiki/.kkrieger
Und noch weiter gedacht: Wie klein kann man eine Welt aus miteinander intelligent agierenden Agenten machen?
Nachtrag: An die Downvoter: Träumt ihr nicht? Vor uns liegen wirklich noch viele völlig irre fantastische Dinge.
Ich weiß, dass die Technik dahinter ziemlich anders ist, aber es erinnert mich an das frühere .kkrieger. Einen kompletten 3D-FPS auf 96 kB zu komprimieren war wirklich cool.
https://en.m.wikipedia.org/wiki/.kkrieger
Wenn man viele Demoscene-Arbeiten sieht und liest, wie sie gemacht werden, versteht man die Grenzen; dann wird klar, dass Elemente wie Schafe, insbesondere die Kegelschnitte der Beine, durch sehr kompakte Gleichungen beschrieben und ähnlich animiert werden können.
Soweit ich weiß, verlassen sich die meisten Demos jedoch auf die GPU und starke 3D-Beschleunigung, während 2D-Demos im Stil japanischer Animation in kleinen Größen selten oder fast nicht vorhanden zu sein scheinen.
Ist 3D-Animation tatsächlich einfacher?
Nebenbei: „mouton“ ist Französisch für „Schaf“, daher auch „mutton“.
Eine „mathematische“ Methode zum Speichern von 2D-Stil-Animationen besteht dagegen im Wesentlichen darin, Konturen als SVG-Kurven zu speichern und für das Füllen von Flächen einen Flood-Fill-Algorithmus zu verwenden.
Grob überschlagen kann schon ein einzelner Bogen oder eine Linie einer Kurve so viel Speicher benötigen wie die Beschreibung eines ganzen geometrischen Volumens; und wenn man auch noch die Animation dieser Kurven speichern will, braucht man viel mehr Platz als für die kleinen Transformationsmatrizen eines 3D-Volumens.
Auch die Komplexität des Rendering-Algorithmus dürfte sowohl in tatsächlicher Algorithmuskomplexität als auch in Raumkomplexität steigen.
Einschränkung: Man könnte auch behaupten, dass das Speichern mehrerer Bitmaps und das Abspielen wie ein Flipbook „mathematisch“ ist, wenn dabei ein prozeduraler Dekompressionsalgorithmus aus den Änderungen ganze Frames erzeugt.
Aber ich sehe nicht, dass es so etwas gibt, und im Vergleich zur Beschreibung von 3D-Volumina wären die Speicheranforderungen enorm.
Es ist etwas größer als 8 kB, aber wenn man unerwartet düstere Animationen über Schafe mag, empfehle ich den Open Movie Cosmos Laundromat der Blender Foundation.
Die Filme dieser Stiftung sind für Tech-Demos immer seltsam düster, aber dieses Werk fand ich besonders gelungen.
[0] https://www.youtube.com/watch?v=Y-rmzh0PI3c
Vorab eine Warnung: Der Film endet mit „to be continued“, und auf der Wikipedia-Seite steht dazu:
„Dieser Film war ursprünglich als Auftakt zu einem Langfilm gedacht. Eine kurze Fortsetzung hatte ein Drehbuch und Designs, ging aber nie in Produktion. 2020 gab [der Macher] bekannt, dass dieser eine Film das gesamte Projekt bleiben werde.“
Wenn ihr euch die Enttäuschung ersparen wollt, das Ende eines interessanten Konzepts wohl nie zu sehen, solltet ihr ihn vielleicht überspringen.
War nützlich für HDR-Experimente in DaVinci Resolve
[1] https://opencontent.netflix.com/#h.uyzoa2bivz2j
8KB ist eine Kategorie der Demoszene. Auf Pouet gibt es einen gut gepflegten Index solcher Werke
0. https://www.pouet.net/prodlist.php?type%5B%5D=8k&page=1
Razor 1911. Reine Nostalgie.
Da kommen viele schöne Erinnerungen von vor Jahrzehnten hoch :-)
Wirklich erstaunlich, und ich mag, wie witzig und kreativ die Geschichte trotz der Einschränkungen ist. Echt beeindruckend
Ich würde gern mehr technische Details dazu hören, mit welchen Tricks und Einsparungen sie Bytes reduziert haben.
In diesem Commit (https://github.com/ctrl-alt-test/mouton/commit/79d2d1eab7a222b434b7041d8fc9bce4e60524f8) wurde eine Performance-Optimierung entfernt, was viele Bytes sparte
Ursprünglich wollten sie sie beibehalten, aber die Bytes reichten nicht, und sie stellten fest, dass diese Optimierung auf halbwegs aktuellen GPUs nicht nötig ist.
Witzig und zugleich völlig verblüffend. Endlich habe ich einen Film gesehen, bei dem ich das Ende nicht vorhersehen konnte.