Ir para a história
Vista do céu, uma baleia-de-bossa passa por um pequeno barco a remos de madeira, num mar azul-profundo riscado pela ondulação.

Como foi feito

Dérive

Como um só par de mãos pintou um oceano sem fim numa página web, e lhe ensinou a respirar.

Thibaud Perrin — conceção, código, modelos 3D, música

Dérive nasceu da vontade de um jogo sereno sobre o oceano. Não um jogo para ganhar: um lugar para andar à deriva, onde uma baleia passa por baixo do barco porque ia para aqueles lados, e tu deixas de remar para a ver.

Dérive é um barco a remos visto do céu, num mar que nunca acaba. Remas, observas e vais enchendo o caderno de Élise Marceau, uma naturalista que partiu em 1911 e cujas páginas regressam a boiar dentro de garrafas. Não há pontuação nem relógio. O mar leva o tempo que precisa.

É obra de uma só pessoa: a conceção, cada linha de código, cada animal e cada cenário modelados no Blender, a direção artística e a música. Corre num navegador, num telemóvel tal como num computador, sem nada para instalar e sem nenhum servidor por trás. Esta página conta como foi feito, e porque tem este aspeto.

Um mar pintado píxel a píxel

Não há nenhuma imagem do mar em Dérive. A cada fotograma, um shader WebGL2 calcula do zero cada píxel da água: duas faixas de ondulação, duas oitavas de encrespado do vento, somadas numa altura, e a inclinação exata dessa altura sob cada píxel. A luz nasce dessa inclinação. Onde uma pequena faceta de água se inclina na medida certa para te devolver o sol aos olhos, cintila.

É assim que o brilho funciona. Ao meio-dia, um fino cintilar branco por toda a vista. Quando o sol está baixo, os clarões esticam-se em traços dourados na sua direção e juntam-se num longo caminho de luz que vem do seu lado, como o verdadeiro, que te acompanha ao longo de uma praia. À noite, um fio de prata sob a lua.

O barco sozinho em água escura, verde-azulada, à hora dourada, os reflexos do sol espalhados pela ondulação em centenas de pequenas faúlhas de ouro.
O Grande Azul à hora dourada: cada faúlha de ouro é uma faceta de água a devolver o sol

Depois, a imagem inteira passa por uma camada pintada. As suas cores são arrastadas ao longo de um campo de pincel que deriva com o mar, ganham um ligeiro relevo e o grão do papel, para que o oceano se leia como uma aguarela e não como uma renderização. A pincelada mede-se em píxeis de ecrã, não em píxeis de renderização: quando um telemóvel cansado tem de desenhar a cena a meia resolução, a pintura mantém o mesmo pincel.

Pôr tudo isto a correr a sessenta fotogramas por segundo num telemóvel foi a maior parte do trabalho. O que muda ao longo de metros e não de píxeis (onde estão os recifes, em que mar estás, as grandes sombras da ondulação) é desenhado uma vez por fotograma em pequenas texturas, a um oitavo do tamanho, e relido filtrado: três leituras de textura em vez de doze a vinte cálculos de ruído por píxel, cinco milissegundos poupados por fotograma sobre os baixios. O mar, o fundo, as criaturas e o que flutua cabem em seis chamadas de desenho antes da camada pintada, mais uma por cada modelo 3D no ecrã.

O mar tinha de parecer pintado, nunca calculado. E tinha de continuar pintado no mais pequeno dos telemóveis.

Um dia dura dez minutos: um minuto de alvorada, cinco de dia, minuto e meio de crepúsculo, dois e meio de noite. As cores não se limitam a escurecer. Cada hora tem a sua paleta, conduzida ao longo de curvas: azul frio e depois rosa na alvorada, ouro e depois violeta ao crepúsculo. O tempo que faz depende do mar e do relógio, por isso todos os que navegam juntos no mesmo mar veem a mesma chuva no mesmo instante, sem que nada passe entre eles.

  • A lagoa na alvorada, banhada de rosa pálido.a alvorada
  • A mesma lagoa no ouro do fim da tarde.a hora dourada
  • A mesma lagoa ao crepúsculo, já violeta.o crepúsculo
  • A mesma lagoa à noite, num azul-profundo.a noite
Uma só lagoa, o barco parado, quatro horas do mesmo dia de dez minutos

Um fundo que cresce por si

Sob os baixios há pradarias de ervas marinhas, cabeços de coral na lagoa, florestas de kelp que se inclinam com a ondulação. Nada disto está modelado, e nada é guardado. Cresce na placa gráfica, a cada fotograma, a partir de simples números.

O truque é que o fundo não tem nenhum buffer de vértices. O leito está cortado em células de seis metros, ancoradas ao mundo. O shader de vértices recebe apenas o seu próprio número, gl_VertexID, e daí deduz a que célula pertence e que lugar ocupa nela. Um pequeno hash da célula e do lugar dá à folha uma posição, um comprimento, uma inclinação. Depois vê quão densa é ali a pradaria: se for rala, a folha dobra-se num triângulo de tamanho zero e a placa gráfica salta-a.

Oito células de fundo, de seis metros cada: em todas, os mesmos lugares tornam-se uma posição por um hash; onde a pradaria é densa tornam-se folhas, onde rareia dobram-se em nada.
Oito células de seis metros: os mesmos lugares em cada uma, que são folhas onde a pradaria é densa e se dobram em nada onde rareia

Uma célula de pradaria leva até 640 folhas, de cinco vértices cada. Não são instanciadas: as instâncias minúsculas custam à placa gráfica por instância, não por vértice, por isso as folhas são desenhadas umas atrás das outras numa só longa tira de triângulos, unidas por triângulos degenerados. Medida, a mesma pradaria custa assim cerca de quarenta por cento menos. Desliza sobre a imagem abaixo para levantar a pradaria da areia.

O mesmo sítio sem o seu fundo: água tingida de verde sobre ondulações de areia nua. Uma pradaria marinha vista de cima, milhares de folhas penteadas pela corrente, o barco ao meio.
com o fundosem

As folhas dobram-se com a corrente, em faixas que rolam pela pradaria. E dão por ti. Cada criatura e o próprio barco ficam impressos, a cada fotograma, numa pequena textura de perturbação que se repete a cada oitenta metros e se desvanece aos poucos: junto ao fundo, junto à superfície, entre os dois. As folhas deitam-se e afastam-se do que passa, as anémonas recolhem-se, a abóbada de kelp abre-se em volta do casco e volta a fechar-se atrás dele.

O barco atravessa uma pradaria marinha, a esteira atrás de si, enquanto as folhas se agitam por baixo.
A remar pelas Pradarias marinhas
O barco esgueira-se por uma floresta de kelp entre blocos de granito, frondes douradas estendidas à superfície.
A esgueirar-se pela floresta de kelp, junto a um leixão

Cada mar tem o seu fundo. Na lagoa, corais-cérebro e corais-mesa, chifres-de-veado de pontas pálidas, gorgónias e corais moles que ondulam, tudo em rosas desmaiados, ocres e cremes, reunidos em redondos cabeços de coral sobre a areia. Na floresta de kelp, estipes de ouro-oliva sobem das suas fixações em direção a frondes estendidas logo abaixo da superfície, sobre um granito incrustado de algas coralinas cor-de-rosa e estrelas-do-mar, e a água entre elas escurece e turva-se quanto mais fundo vão.

Uma lagoa turquesa sobre um recife de corais arredondados em suaves tons pastel, o barco à deriva por cima.
Os cabeços de coral da lagoa
Uma floresta de kelp vista de cima: frondes douradas sobre recifes escuros e seixos claros.
A floresta de kelp, inclinada pela ondulação

Criaturas que nadam, e não deslizam

Peixes, tubarões, tartarugas, raias e baleias vivem numa pequena simulação escrita em Rust e compilada para WebAssembly. É minúscula de propósito: sem biblioteca padrão, sem alocador, sem importações, todo o seu estado num único bloco fixo de memória, de modo que a página lê as posições das criaturas diretamente dali, sem copiar um único byte. Compilada, pesa 11,7 kilobytes. Os cardumes seguem o seu guia, os tubarões andam em círculos, as baleias sobem à superfície nos segundos antes de respirar e só sopram quando têm o dorso perto dela. Uma cópia da mesma simulação em JavaScript assume o comando onde o WebAssembly está bloqueado, e um teste põe as duas a avançar ao mesmo passo para que nunca se afastem.

Depois, cada animal tem de se mover como ele próprio. Cada modelo nasce no Blender já a pensar no seu nado: pesos pintados nas cores dos vértices, vermelho para a onda do corpo, verde para as barbatanas ou as asas, azul para as partes finas que estremecem. O shader de vértices manda uma onda da cabeça ao longo do corpo, bate as barbatanas, faz ondular as bordas e lê a curva da criatura de um fotograma para o outro, de modo que a coluna se dobra ao longo do arco que nada e o corpo se inclina para dentro da curva. Uma baleia vira numa longa curva do seu próprio comprimento; uma raia-manta inclina as asas como um planador.

Ao vivo, no teu navegador: o modelo do jogo e o seu nado. Arrasta-o para o fazer girar. Megaptera novaeangliae

A profundidade pinta-se, não se esbate. Um corpo debaixo de água nunca é transparente: o dorso apanha mais luz do que os flancos, a cor da água vai ganhando ponto a ponto, as bordas desaparecem primeiro, e de dia os reflexos do sol correm pelos dorsos perto da superfície. Vista do céu, uma baleia a doze metros de profundidade é uma forma que adivinhas antes de a veres.

Alguns animais só se encontram com paciência. Fica calmo ao lado deles, remos parados, o isco certo na água, e o encontro vai-se enchendo como um fôlego suspenso. Quando se completa, a baleia responde com um sopro ao lado do barco. Se navegares com amigos, conta também para eles.

O caderno: primeiro o lápis, depois a aguarela

Cada animal com que te cruzas entra no caderno de Élise: cinquenta e uma espécies que existem todas, menos uma. A maneira como o caderno as desenha acompanha o quanto as conheces. Cruzada uma vez, um esboço a lápis: um duplo contorno hesitante, tracejado conforme a luz, a grafite presa no grão do papel. Vista vezes suficientes, chegam as suas cores. E quando moes os pigmentos de que precisa com o que o mar te dá (nácar para o branco, vidro do mar para o azul, ferrugem para o ocre, fuligem para o negro), torna-se uma prancha em aguarela: aguadas que transbordam do contorno, pigmento acumulado nas bordas molhadas, o dorso iluminado deixado em papel nu.

Nenhuma destas pranchas foi pintada à mão. O jogo tira-as dos mesmos modelos 3D que nadam no seu mar, em duas passagens sobre as cores e a forma do modelo, na primeira vez que abres a página.

Um esboço a lápis de uma baleia-de-bossa, tracejado sobre um contorno hesitante. cruzada: o lápis
A mesma baleia-de-bossa numa prancha em aguarela, em cinzentos e azuis. pintada: a aguarela

O carregamento, em aguarela

Um jogo tem de carregar. Aqui, a espera faz parte dele. A página abre-se sobre papel; a tinta escreve «Dérive» letra a letra, depois uma aguada de aguarela espalha-se sobre uma de quatro cartas náuticas pintadas, e essa aguada é a barra de progresso. Quando o mar por trás está pronto, escolhes entrar com som ou em silêncio, e a carta pintada mergulha no oceano vivo.

A aguada é um script de vinte e dois kilobytes com o seu próprio pequeno programa WebGL: sete manchas que avançam através de um deslocamento rasgado, uma faixa mais escura de pigmento molhado na sua frente, a carta a rodopiar e a assentar à medida que se enche. Corre num worker, numa tela fora do ecrã, para que o arranque pesado do jogo nunca a faça engasgar. As duas fontes do título vão embutidas na página, reduzidas a um ou dois kilobytes, para que a tinta escreva logo na primeiríssima pintura.

O ecrã de carregamento no início: «Dérive» a tinta sobre papel creme, uma carta náutica em aguarela só meio tingida, as bordas ainda rasgadas. O mesmo ecrã de carregamento uns segundos depois, toda a carta náutica tingida à volta do título.
Continua a descer: a carta vai-se tingindo, como enquanto o mar carrega

Um mundo sem servidor

Dérive é um site estático. Não há servidor de jogo, nem base de dados, nada para manter a funcionar. Cada mar nasce de um só número, legível como um código curto do género J9C-HA4W: o mesmo código dá os mesmos recifes, as mesmas pessoas, o mesmo tempo, em qualquer dispositivo. O teu caderno vive no teu dispositivo. Se criares uma conta, o teu jogo é cifrado e assinado no teu dispositivo antes de uma cópia ficar em relays públicos, por isso mais ninguém o pode ler, nem sequer o autor do jogo.

Navegar juntos funciona da mesma maneira. Os barcos encontram-se através desses relays e depois falam diretamente, de navegador para navegador, por WebRTC; o código da partida é também a sua palavra-passe. O estado de um barco ocupa cinquenta e dois bytes, dez vezes por segundo. Quem lidera um grupo simula as criaturas para todos os que estão perto, para que todos vejam a mesma baleia.

E o mar é mesmo sem fim. Os números de vírgula flutuante perdem precisão longe da origem, e a cinquenta quilómetros os peixes mais lentos ter-se-iam imobilizado. Por isso o mundo recentra-se discretamente no barco enquanto remas, e mantém-se exato até dezasseis mil quilómetros: quatro meses a remar em linha reta.

Em alguns números

Fotogramas por segundo, num telemóvel60
A simulação das criaturas, compilada11,7 KB
Folhas de pradaria numa célula de seis metros640
Espécies no caderno de Élise51
Mares possíveis, cada um de um só número4,3 mil milhões
Quilómetros antes de o mar perder precisão16 000
Servidores a manter0

A música

A música foi composta para o jogo. Cada um dos oito mares tem a sua peça: a da lagoa leve e quente, a dos mares frios lenta e ampla, a do abismo grave e paciente; a noite tem a sua, e uma tempestade sobrepõe-se a tudo enquanto dura. Ao remar de um mar para o seguinte, as peças fundem-se em seis segundos, e baixam um pouco quando um tubarão se aproxima.

O resto do som é criado ao vivo pelo navegador: o murmúrio do mar, o ranger dos remos, o sopro das baleias, a chuva, o trovão que rola uns segundos depois do relâmpago, mais longe ou mais perto. Com auscultadores, é melhor.

«Accueil», o tema do ecrã de boas-vindas — Thibaud Perrin

O mar está à tua espera.

Dérive é gratuito, no teu navegador, num telemóvel ou num computador. Auscultadores postos, remos na água.

Fazer-se ao mar

Fiz o Dérive sozinho: cada linha de código, cada animal e cada naufrágio modelados no Blender, cada nota da música. Foi um trabalho lento, e feliz; espero que um pouco dessa calma te chegue, remos parados, enquanto passa uma baleia. — Thibaud Perrin. Algo a dizer? Escreve-me.