Ir al relato
Vista desde el cielo, una ballena jorobada pasa junto a una pequeña barca de madera sobre un mar azul profundo surcado por el oleaje.

Cómo se hizo

Dérive

Cómo un solo par de manos pintó un océano sin fin en una página web, y le enseñó a respirar.

Thibaud Perrin — diseño, código, modelos 3D, música

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.

La barca sola sobre un agua oscura verde azulada a la hora dorada, los reflejos del sol esparcidos por el oleaje en cientos de pequeñas motas de oro.
El Gran Azul a la hora dorada: cada mota de oro es una faceta de agua que devuelve el sol

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.

  • La laguna al alba, bañada de rosa pálido.el alba
  • La misma laguna en el oro del final de la tarde.la hora dorada
  • La misma laguna al anochecer, vuelta violeta.el crepúsculo
  • La misma laguna de noche, en azul profundo.la noche
Una sola laguna, la barca quieta, cuatro horas del mismo día de diez minutos

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.

Ocho celdas de fondo, de seis metros cada una: en todas, los mismos huecos se convierten en un lugar mediante un hash; donde la pradera es densa se vuelven hojas, donde ralea se pliegan en nada.
Ocho celdas de seis metros: los mismos huecos en cada una, que son hojas donde la pradera es densa y se pliegan en nada donde ralea

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.

El mismo lugar sin su fondo: agua teñida de verde sobre ondas de arena desnuda. Una pradera marina vista desde arriba, miles de hojas peinadas por la corriente, la barca en medio.
con el fondosin él

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.

La barca cruza una pradera marina, su estela detrás, mientras las hojas se agitan bajo ella.
Remando a través de las Praderas marinas
La barca se abre paso por un bosque de kelp entre bloques de granito, con frondas doradas que se estiran en la superficie.
Abriéndose paso por el bosque de kelp, junto a un farallón

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.

Una laguna turquesa sobre un arrecife de corales redondeados en suaves tonos pastel, la barca a la deriva encima.
Los cabezos de coral de la laguna
Un bosque de kelp visto desde arriba: frondas doradas sobre arrecifes oscuros y guijarros claros.
El bosque de kelp, inclinado por la marejada

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.

En directo, en tu navegador: el modelo del juego y su nado. Arrástralo para girarlo. Megaptera novaeangliae

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.

Un boceto a lápiz de una ballena jorobada, trazos sombreados sobre un contorno vacilante. vista: el lápiz
La misma ballena jorobada como lámina de acuarela, en grises y azules. pintada: la acuarela

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.

La pantalla de carga al principio: «Dérive» en tinta sobre papel crema, una carta marina en acuarela a medio teñir, con los bordes aún desgarrados. La misma pantalla de carga unos segundos después, con toda la carta marina teñida alrededor del título.
Sigue bajando: la carta se tiñe, como mientras carga el mar

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

Fotogramas por segundo, en un teléfono60
La simulación de las criaturas, compilada11,7 KB
Hojas de pradera en una celda de seis metros640
Especies en el cuaderno de Élise51
Mares posibles, cada uno de un solo número4300 millones
Kilómetros antes de que el mar pierda precisión16 000
Servidores que mantener0

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.

«Accueil», el tema de la pantalla de bienvenida — Thibaud Perrin

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 mar

Hice 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.