Am Anfang von Dérive stand der Wunsch nach einem sanften Spiel über das Meer. Kein Spiel zum Gewinnen: ein Ort zum Treibenlassen, an dem ein Wal unter dem Boot hindurchzieht, weil er ohnehin in diese Richtung wollte, und du hörst auf zu rudern, um ihm zuzusehen.
Dérive ist ein Ruderboot, vom Himmel aus gesehen, auf einem Meer, das nie endet. Du ruderst, du schaust, und du füllst das Notizbuch von Élise Marceau, einer Naturforscherin, die 1911 aufbrach und deren Seiten in Flaschen zurücktreiben. Es gibt keine Punkte und keine Uhr. Das Meer nimmt sich die Zeit, die es braucht.
Es ist das Werk eines einzigen Menschen: die Gestaltung, jede Zeile Code, jedes Tier und jedes Stück Kulisse, in Blender modelliert, die künstlerische Leitung und die Musik. Es läuft im Browser, auf dem Handy genauso wie am Schreibtisch, ohne Installation und ohne einen Server dahinter. Diese Seite erzählt, wie es entstanden ist und warum es so aussieht.
Ein Meer, Pixel für Pixel gemalt
In Dérive gibt es nirgends ein Bild vom Meer. In jedem Frame berechnet ein WebGL2-Shader jeden Pixel des Wassers von Grund auf: zwei Bänder Dünung, zwei Oktaven Windkräuseln, zu einer Höhe aufsummiert, und die genaue Neigung dieser Höhe unter jedem einzelnen Pixel. Aus dieser Neigung entsteht das Licht. Wo eine kleine Wasserfacette genau so kippt, dass sie dir die Sonne ins Auge spiegelt, blitzt sie auf.
So entsteht das Glitzern. Mittags ein feines weißes Funkeln über die ganze Sicht. Steht die Sonne tief, ziehen sich die Blitze zu goldenen Strichen in ihrer Richtung und sammeln sich zu einer langen Lichtstraße, die von ihrer Seite hereinkommt, so wie die echte, die dir am Strand entlang folgt. Nachts ein schmaler Silberpfad unter dem Mond.
Dann geht das ganze Bild durch eine gemalte Schicht. Seine Farben werden entlang eines Pinselfelds gezogen, das mit dem Meer treibt, ein wenig geprägt und gekörnt wie Papier, damit sich der Ozean wie ein Aquarell liest und nicht wie ein Rendering. Der Pinselstrich bemisst sich in Bildschirmpixeln, nicht in Renderpixeln: Wenn ein müdes Handy die Szene in halber Auflösung zeichnen muss, behält die Malerei denselben Pinsel.
Das auf einem Handy mit sechzig Bildern pro Sekunde laufen zu lassen, war der größte Teil der Arbeit. Was sich über Meter statt über Pixel ändert (wo die Riffe liegen, in welchem Meer du bist, die großen Schatten der Dünung), wird einmal pro Frame in kleine Texturen gezeichnet, in einem Achtel der Größe, und gefiltert zurückgelesen: drei Texturzugriffe statt zwölf bis zwanzig Rauschberechnungen pro Pixel, fünf Millisekunden pro Frame über den Untiefen gespart. Meer, Meeresgrund, Tiere und alles, was treibt, passen in sechs Zeichenaufrufe vor der gemalten Schicht, dazu einer pro 3D-Modell auf dem Bildschirm.
Das Meer sollte sich gemalt anfühlen, nie berechnet. Und es sollte auch auf dem kleinsten Handy gemalt bleiben.
Ein Tag dauert zehn Minuten: eine Minute Morgengrauen, fünf Tag, anderthalb Dämmerung, zweieinhalb Nacht. Die Farben werden nicht einfach dunkler. Jede Stunde hat ihre eigene Palette, entlang von Kurven übergeblendet: kaltes Blau, dann Rosa im Morgengrauen, Gold, dann Violett in der Dämmerung. Das Wetter hängt vom Meer und von der Uhr ab, sodass alle, die zusammen auf demselben Meer segeln, im selben Augenblick denselben Regen sehen, ohne dass zwischen ihnen etwas gesendet wird.
Morgengrauen
goldene Stunde
Dämmerung
Nacht
Ein Meeresgrund, der von selbst wächst
Unter den Untiefen liegen Seegraswiesen, Korallenstöcke in der Lagune, Kelpwälder, die sich mit der Brandung neigen. Nichts davon ist modelliert, und nichts davon ist gespeichert. Es wächst auf der Grafikkarte, in jedem Frame, aus nichts als Zahlen.
Der Kniff: Der Meeresgrund hat überhaupt keine Vertex-Puffer. Der Boden ist in sechs Meter breite Zellen geschnitten, fest in der Welt verankert. Der Vertex-Shader bekommt nur seine eigene Nummer, gl_VertexID, und errechnet daraus, zu welcher Zelle er gehört und welchen Platz er darin hat. Ein kleiner Hash aus Zelle und Platz gibt dem Halm einen Ort, eine Länge, eine Neigung. Dann schaut er, wie dicht die Wiese dort ist: Ist sie dünn, faltet sich der Halm zu einem Dreieck der Größe null, und die Grafikkarte überspringt ihn.
Eine Wiesenzelle hält bis zu 640 Halme mit je fünf Vertices. Sie werden nicht instanziert: Winzige Instanzen kosten die Grafikkarte pro Instanz, nicht pro Vertex, also werden die Halme hintereinander in einem einzigen langen Dreiecksstreifen gezeichnet, verbunden durch entartete Dreiecke. Gemessen kostet dieselbe Wiese so etwa vierzig Prozent weniger. Wisch über das Bild unten, um die Wiese vom Sand zu heben.
Die Halme biegen sich mit der Strömung, in Bändern, die über die Wiese rollen. Und sie bemerken dich. Jedes Tier und das Boot selbst werden in jedem Frame in eine kleine Störungstextur getupft, die sich alle achtzig Meter wiederholt und nach und nach verblasst: nah am Grund, nah an der Oberfläche, dazwischen. Die Halme legen sich hin und weichen aus, wenn etwas vorbeizieht, Anemonen ziehen sich zusammen, das Kelpdach öffnet sich um den Rumpf und schließt sich hinter ihm wieder.
Jedes Meer hat seinen eigenen Grund. In der Lagune Hirn- und Tischkorallen, Geweihkorallen mit hellen Spitzen, Seefächer und Weichkorallen, die sich wiegen, alles in verblichenem Rosa, Ocker und Creme, zu runden Korallenstöcken auf dem Sand versammelt. Im Kelpwald steigen olivgoldene Stiele von ihren Haftkrallen zu Wedeln auf, die knapp unter der Oberfläche treiben, über Granit, verkrustet mit rosa Kalkalgen und Seesternen, und das Wasser zwischen ihnen wird dunkler und trüber, je tiefer sie reichen.
Tiere, die schwimmen, statt zu gleiten
Fische, Haie, Schildkröten, Rochen und Wale leben in einer kleinen Simulation, geschrieben in Rust und zu WebAssembly kompiliert. Sie ist bewusst winzig: keine Standardbibliothek, kein Allokator, keine Importe, ihr ganzer Zustand in einem einzigen festen Speicherblock, sodass die Seite die Positionen der Tiere direkt daraus liest, ohne ein Byte zu kopieren. Kompiliert wiegt sie 11,7 Kilobyte. Schwärme folgen ihrem Anführer, Haie kreisen, Wale steigen in den Sekunden vor dem Atmen zur Oberfläche auf und blasen erst, wenn ihr Rücken sie fast erreicht. Eine Kopie derselben Simulation in JavaScript springt ein, wo WebAssembly blockiert ist, und ein Test lässt beide im Gleichschritt laufen, damit sie nie auseinanderdriften.
Dann muss sich jedes Tier wie es selbst bewegen. Jedes Modell entsteht in Blender schon mit Blick auf seine Bewegung: Gewichte, in seine Vertexfarben gemalt, Rot für die Welle des Körpers, Grün für Flossen oder Flügel, Blau für dünne Teile, die flattern. Der Vertex-Shader schickt eine Welle vom Kopf den Körper hinunter, schlägt die Flossen, lässt die Ränder kräuseln und liest die Drehung des Tieres von Frame zu Frame, sodass sich die Wirbelsäule entlang des Bogens krümmt, den es schwimmt, und der Körper sich in die Kurve legt. Ein Wal zieht in einem langen Bogen von seiner eigenen Länge herum; ein Manta neigt die Flügel wie ein Segelflugzeug.
Tiefe wird gemalt, nicht ausgeblendet. Ein Körper unter Wasser ist nie durchsichtig: Der Rücken fängt mehr Licht als die Flanken, die Farbe des Wassers gewinnt Punkt für Punkt, die Ränder verschwinden zuerst, und tagsüber laufen die Lichtkringel der Sonne über Rücken nahe der Oberfläche. Vom Himmel aus gesehen ist ein Wal in zwölf Metern Tiefe eine Gestalt, die du ahnst, bevor du sie siehst.
Manchen Tieren begegnest du nur mit Geduld. Bleib ruhig neben ihnen, die Ruder still, den richtigen Köder im Wasser, und die Begegnung füllt sich wie ein angehaltener Atem. Ist es so weit, antwortet der Wal mit einem Atemzug neben dem Boot. Segeln Freunde mit dir, zählt es auch für sie.
Das Notizbuch: erst der Bleistift, dann das Aquarell
Jedes Tier, dem du begegnest, kommt in Élises Notizbuch: einundfünfzig Arten, die es alle gibt, bis auf eine. Wie das Notizbuch sie zeichnet, hängt davon ab, wie gut du sie kennst. Einmal gekreuzt, eine Bleistiftskizze: ein zittriger doppelter Umriss, Schraffur nach dem Licht, Graphit, der im Korn des Papiers hängen bleibt. Oft genug gesehen, kommen ihre Farben. Und wenn du aus dem, was das Meer dir gibt, die Pigmente reibst, die sie braucht (Perlmutt für Weiß, Meerglas für Blau, Rost für Ocker, Ruß für Schwarz), wird sie zu einer Aquarelltafel: Lasuren, die über den Umriss hinauslaufen, Pigment, das sich an den nassen Rändern sammelt, der beleuchtete Rücken als nacktes Papier ausgespart.
Keine dieser Tafeln wurde von Hand gemalt. Das Spiel zeichnet sie aus denselben 3D-Modellen, die in seinem Meer schwimmen, in zwei Durchgängen über Farben und Form des Modells, wenn du die Seite zum ersten Mal aufschlägst.
gekreuzt: der Bleistift
gemalt: das Aquarell
Grüne Meeresschildkröte Chelonia mydas
Mantarochen Mobula birostris
Orca Orcinus orca
Langschnäuziges Seepferdchen Hippocampus guttulatus
Gemeiner Krake Octopus vulgaris
Gelbe Haarqualle Cyanea capillata
Das Laden, als Aquarell
Ein Spiel muss laden. Hier gehört das Warten dazu. Die Seite öffnet sich auf Papier; die Tinte schreibt „Dérive“ Buchstabe für Buchstabe, dann breitet sich eine Aquarelllasur über eine von vier gemalten Seekarten aus, und diese Lasur ist der Ladebalken. Ist das Meer dahinter bereit, wählst du, ob du mit Ton oder in Stille eintrittst, und die gemalte Karte taucht in den lebendigen Ozean.
Die Lasur ist ein Skript von zweiundzwanzig Kilobyte mit seinem eigenen kleinen WebGL-Programm: sieben Flecken, die sich durch eine zerrissene Verschiebung vorschieben, ein dunkleres Band nassen Pigments an ihrer Front, die Karte, die wirbelt und sich setzt, während sie sich füllt. Sie läuft in einem Worker auf einer Offscreen-Leinwand, sodass der schwere Start des Spiels sie nie ins Stocken bringt. Die beiden Schriften des Titels liegen als Untermengen von ein, zwei Kilobyte direkt in der Seite, damit die Tinte schon beim allerersten Zeichnen schreibt.
Eine Welt ohne Server
Dérive ist eine statische Website. Es gibt keinen Spielserver, keine Datenbank, nichts, das am Laufen gehalten werden muss. Jedes Meer entsteht aus einer einzigen Zahl, lesbar als kurzer Code wie J9C-HA4W: Derselbe Code ergibt dieselben Riffe, dieselben Menschen, dasselbe Wetter, auf jedem Gerät. Dein Notizbuch lebt auf deinem Gerät. Legst du ein Konto an, wird dein Spiel auf deinem Gerät verschlüsselt und signiert, bevor eine Kopie auf öffentlichen Relays abgelegt wird, sodass niemand sonst es lesen kann, nicht einmal der Autor des Spiels.
Gemeinsam segeln funktioniert genauso. Die Boote finden sich über diese Relays und sprechen dann direkt miteinander, von Browser zu Browser, über WebRTC; der Code der Partie ist zugleich ihr Passwort. Der Zustand eines Bootes passt in zweiundfünfzig Byte, zehnmal pro Sekunde. Wer eine Gruppe anführt, simuliert die Tiere für alle in der Nähe, sodass ihr alle denselben Wal seht.
Und das Meer ist wirklich endlos. Gleitkommazahlen verlieren weit vom Ursprung ihre Genauigkeit, und nach fünfzig Kilometern wären die langsamsten Fische erstarrt. Also zentriert sich die Welt leise neu auf das Boot, während du ruderst, und bleibt genau bis sechzehntausend Kilometer hinaus: vier Monate Rudern geradeaus.
In ein paar Zahlen
Die Musik
Die Musik wurde für das Spiel komponiert. Jedes der acht Meere hat sein eigenes Stück, das der Lagune leicht und warm, das der kalten Meere langsam und weit, das der Tiefsee dunkel und geduldig; die Nacht hat ihr eigenes, und ein Sturm übertönt alles, solange er dauert. Ruderst du von einem Meer ins nächste, blenden die Stücke über sechs Sekunden ineinander, und sie werden ein wenig leiser, wenn ein Hai näher kommt.
Den Rest des Klangs erzeugt der Browser live: das Rauschen des Meeres, das Knarren der Ruder, den Atem der Wale, Regen, Donner, der ein paar Sekunden nach dem Blitz heranrollt, ferner oder näher. Kopfhörer helfen.
Das Meer wartet.
Dérive ist kostenlos, in deinem Browser, auf dem Handy oder am Schreibtisch. Kopfhörer auf, Ruder raus.
In See stechenIch habe Dérive allein gemacht: jede Zeile Code, jedes Tier und jedes Wrack in Blender modelliert, jede Note der Musik. Es war langsame Arbeit, und eine glückliche; ich hoffe, etwas von dieser Ruhe erreicht dich, die Ruder still, wenn ein Wal vorüberzieht. — Thibaud Perrin. Etwas zu sagen? Schreib mir.