Dérive nació del deseo de un juego tranquilo sobre el océano. No un juego para ganar: un lugar donde dejarse llevar, donde una ballena pasa bajo la barca porque iba hacia allí, y tú dejas de remar para mirarla.
Dérive es una barca vista desde el cielo, en un mar que nunca termina. Remas, miras y vas llenando el cuaderno de Élise Marceau, una naturalista que zarpó en 1911 y cuyas páginas vuelven flotando dentro de botellas. No hay puntuación ni reloj. El mar se toma el tiempo que necesita.
Es obra de una sola persona: el diseño, cada línea de código, cada animal y cada decorado modelados en Blender, la dirección artística y la música. Funciona en un navegador, en un teléfono igual que en un ordenador, sin nada que instalar y sin ningún servidor detrás. Esta página cuenta cómo se hizo, y por qué se ve así.
Un mar pintado píxel a píxel
En Dérive no hay ninguna imagen del mar. En cada fotograma, un shader de WebGL2 calcula desde cero cada píxel del agua: dos bandas de mar de fondo, dos octavas de rizos de viento, sumadas en una altura, y la pendiente exacta de esa altura bajo cada píxel. La luz nace de esa pendiente. Allí donde una pequeña faceta de agua se inclina justo lo necesario para devolverte el sol a los ojos, destella.
Así funciona el centelleo. A mediodía, un fino brillo blanco por toda la vista. Cuando el sol está bajo, los destellos se alargan en trazos dorados en su dirección y se reúnen en un largo camino de luz que llega desde su lado, como el de verdad, que te sigue a lo largo de una playa. De noche, un estrecho sendero de plata bajo la luna.
Después, la imagen entera pasa por una capa pintada. Sus colores se arrastran a lo largo de un campo de pincel que deriva con el mar, se realzan un poco y toman el grano del papel, para que el océano se lea como una acuarela y no como un render. El trazo se mide en píxeles de pantalla, no de render: cuando un teléfono cansado tiene que dibujar la escena a media resolución, la pintura conserva el mismo pincel.
Hacer que todo eso funcione a sesenta fotogramas por segundo en un teléfono fue la mayor parte del trabajo. Lo que cambia a lo largo de metros y no de píxeles (dónde están los arrecifes, en qué mar estás, las grandes sombras del oleaje) se dibuja una vez por fotograma en pequeñas texturas, a un octavo del tamaño, y se vuelve a leer filtrado: tres lecturas de textura en lugar de doce a veinte cálculos de ruido por píxel, cinco milisegundos ganados por fotograma sobre los bajíos. El mar, el fondo, las criaturas y lo que flota caben en seis llamadas de dibujo antes de la capa pintada, más una por cada modelo 3D en pantalla.
El mar tenía que parecer pintado, nunca calculado. Y tenía que seguir pintado en el teléfono más pequeño.
Un día dura diez minutos: un minuto de alba, cinco de día, minuto y medio de crepúsculo, dos y medio de noche. Los colores no se limitan a oscurecerse. Cada hora tiene su propia paleta, llevada a lo largo de curvas: azul frío y luego rosa al alba, oro y luego violeta al atardecer. El tiempo que hace depende del mar y del reloj, así que todos los que navegan juntos por el mismo mar ven la misma lluvia en el mismo instante, sin que nada viaje entre ellos.
el alba
la hora dorada
el crepúsculo
la noche
Un fondo que crece por sí solo
Bajo los bajíos hay praderas marinas, cabezos de coral en la laguna, bosques de kelp que se inclinan con la marejada. Nada de eso está modelado, y nada se guarda. Todo crece en la tarjeta gráfica, en cada fotograma, a partir de simples números.
El truco es que el fondo no tiene ningún búfer de vértices. El lecho se corta en celdas de seis metros, ancladas al mundo. El shader de vértices solo recibe su propio número, gl_VertexID, y de él deduce a qué celda pertenece y qué hueco ocupa en ella. Un pequeño hash de la celda y del hueco le da a la hoja un lugar, una longitud, una inclinación. Luego mira lo densa que es la pradera allí: si es rala, la hoja se pliega en un triángulo de tamaño cero y la tarjeta gráfica se la salta.
Una celda de pradera tiene hasta 640 hojas, de cinco vértices cada una. No se instancian: las instancias diminutas le cuestan a la tarjeta gráfica por instancia, no por vértice, así que las hojas se dibujan una tras otra en una sola tira de triángulos, unidas por triángulos degenerados. Medido, la misma pradera cuesta así cerca de un cuarenta por ciento menos. Desliza sobre la imagen de abajo para levantar la pradera de la arena.
Las hojas se doblan con la corriente en franjas que ruedan por la pradera. Y se dan cuenta de que estás ahí. Cada criatura y la propia barca se estampan, en cada fotograma, en una pequeña textura de perturbación que se repite cada ochenta metros y se desvanece poco a poco: cerca del fondo, cerca de la superficie, entre ambos. Las hojas se tumban y se apartan de lo que pasa, las anémonas se cierran, el dosel de kelp se abre alrededor del casco y vuelve a cerrarse detrás.
Cada mar tiene su propio fondo. En la laguna, corales cerebro y corales mesa, cuernos de ciervo de puntas pálidas, gorgonias y corales blandos que se mecen, todo en rosas desvaídos, ocres y cremas, reunidos en redondos cabezos de coral sobre la arena. En el bosque de kelp, estipes de oro oliva se alzan desde sus rizoides hacia frondas que se estiran justo bajo la superficie, sobre un granito incrustado de algas coralinas rosadas y estrellas de mar, y el agua entre ellos se oscurece y se enturbia cuanto más hondos están.
Criaturas que nadan, no que se deslizan
Peces, tiburones, tortugas, rayas y ballenas viven en una pequeña simulación escrita en Rust y compilada a WebAssembly. Es diminuta a propósito: sin biblioteca estándar, sin asignador de memoria, sin importaciones, todo su estado en un único bloque fijo de memoria, así que la página lee las posiciones de las criaturas directamente de él sin copiar un solo byte. Compilada, pesa 11,7 kilobytes. Los bancos siguen a su guía, los tiburones dan vueltas, las ballenas suben hacia la superficie en los segundos antes de respirar y solo soplan cuando tienen el lomo cerca de ella. Una copia de la misma simulación en JavaScript toma el relevo donde WebAssembly está bloqueado, y una prueba hace avanzar a las dos al mismo paso para que nunca se separen.
Luego, cada animal tiene que moverse como él mismo. Cada modelo se hace en Blender pensando en su nado: pesos pintados en los colores de sus vértices, rojo para la onda del cuerpo, verde para las aletas o las alas, azul para las partes finas que tiemblan. El shader de vértices lanza una onda desde la cabeza a lo largo del cuerpo, bate las aletas, hace ondular los bordes y lee el giro de la criatura de un fotograma a otro, de modo que la columna se curva siguiendo el arco que nada y el cuerpo se inclina hacia el giro. Una ballena gira en una larga curva de su propia longitud; una manta ladea las alas como un planeador.
La profundidad se pinta, no se difumina. Un cuerpo bajo el agua nunca es transparente: el lomo recibe más luz que los flancos, el color del agua va ganando punto a punto, los bordes se pierden primero, y de día los reflejos del sol recorren los lomos cercanos a la superficie. Vista desde el cielo, una ballena a doce metros de profundidad es una forma que adivinas antes de verla.
A algunos animales solo los encuentras con paciencia. Quédate tranquilo a su lado, con los remos quietos y el cebo adecuado en el agua, y el encuentro se va llenando como una respiración contenida. Cuando se completa, la ballena responde con un soplido junto a la barca. Si navegas con amigos, también cuenta para ellos.
El cuaderno: primero el lápiz, luego la acuarela
Cada animal con el que te cruzas entra en el cuaderno de Élise: cincuenta y una especies que existen todas, menos una. La forma en que el cuaderno las dibuja depende de lo bien que las conoces. Vista una vez, un boceto a lápiz: un doble contorno vacilante, sombreado según la luz, el grafito prendido en el grano del papel. Vista lo bastante a menudo, llegan sus colores. Y cuando mueles los pigmentos que necesita con lo que te da el mar (nácar para el blanco, vidrio marino para el azul, óxido para el ocre, hollín para el negro), se convierte en una lámina de acuarela: aguadas que desbordan el contorno, pigmento acumulado en los bordes húmedos, el lomo iluminado dejado en papel desnudo.
Ninguna de estas láminas se pintó a mano. El juego las saca de los mismos modelos 3D que nadan en su mar, en dos pasadas sobre los colores y la forma del modelo, la primera vez que abres la página.
vista: el lápiz
pintada: la acuarela
Tortuga verde Chelonia mydas
Mantarraya Mobula birostris
Orca Orcinus orca
Caballito de mar narizón Hippocampus guttulatus
Pulpo Octopus vulgaris
Medusa melena de león Cyanea capillata
La carga, en acuarela
Un juego tiene que cargar. Aquí, la espera forma parte de él. La página se abre sobre papel; la tinta escribe «Dérive» letra a letra, luego una aguada de acuarela se extiende sobre una de cuatro cartas marinas pintadas, y esa aguada es la barra de progreso. Cuando el mar de detrás está listo, eliges entrar con sonido o en silencio, y la carta pintada se zambulle en el océano vivo.
La aguada es un script de veintidós kilobytes con su propio pequeño programa WebGL: siete manchas que avanzan a través de un desplazamiento desgarrado, una franja más oscura de pigmento húmedo en su frente, la carta que gira y se asienta a medida que se llena. Funciona en un worker sobre un lienzo fuera de pantalla, así que el pesado arranque del juego nunca la hace tartamudear. Las dos tipografías del título van incrustadas en la página, reducidas a uno o dos kilobytes, para que la tinta escriba desde el primer instante.
Un mundo sin servidor
Dérive es un sitio estático. No hay servidor de juego, ni base de datos, nada que mantener en marcha. Cada mar sale de un solo número, legible como un código corto del tipo J9C-HA4W: el mismo código da los mismos arrecifes, la misma gente, el mismo tiempo, en cualquier dispositivo. Tu cuaderno vive en tu dispositivo. Si creas una cuenta, tu partida se cifra y se firma en tu dispositivo antes de dejar una copia en relés públicos, así que nadie más puede leerla, ni siquiera el autor del juego.
Navegar juntos funciona igual. Las barcas se encuentran a través de esos relés y luego hablan directamente, de navegador a navegador, por WebRTC; el código de la partida es también su contraseña. El estado de una barca ocupa cincuenta y dos bytes, diez veces por segundo. Quien guía un grupo simula las criaturas para todos los que están cerca, así que todos miráis la misma ballena.
Y el mar es de verdad infinito. Los números de coma flotante pierden precisión lejos del origen, y a cincuenta kilómetros los peces más lentos se habrían quedado congelados. Así que el mundo se recentra en silencio sobre la barca mientras remas, y sigue siendo exacto hasta dieciséis mil kilómetros: cuatro meses remando en línea recta.
En unas cifras
La música
La música se compuso para el juego. Cada uno de los ocho mares tiene su pieza: la de la laguna, ligera y cálida; la de los mares fríos, lenta y amplia; la del abismo, grave y paciente; la noche tiene la suya, y una tormenta se impone a todo mientras dura. Al remar de un mar al siguiente, las piezas se funden en seis segundos, y bajan un poco cuando se acerca un tiburón.
El resto del sonido lo crea el navegador en directo: el rumor del mar, el crujido de los remos, el soplido de las ballenas, la lluvia, el trueno que rueda unos segundos después del relámpago, más lejos o más cerca. Con auriculares, mejor.
El mar te espera.
Dérive es gratuito, en tu navegador, en un teléfono o en un ordenador. Auriculares puestos, remos al agua.
Hacerse a la marHice Dérive solo: cada línea de código, cada animal y cada pecio modelados en Blender, cada nota de la música. Fue un trabajo lento, y feliz; ojalá algo de esa calma te llegue, con los remos quietos, mientras pasa una ballena. — Thibaud Perrin. ¿Algo que decirme? Escríbeme.