BASTIDORES · CÓDIGO E EQUAÇÕES
O que tem nessa página.
Quase tudo que se move aqui é meteorologia rodando ao vivo no seu navegador. Nada é vídeo, nada é GIF: são equações resolvidas a cada quadro.
Duas peças fazem o trabalho pesado. O fundo desta página é um campo de pressão sintético do qual se extrai o vento geostrófico, isóbara por isóbara. E o box de 10 km na página inicial é um raymarch volumétrico de nuvens escrito em WebGL, sem nenhuma biblioteca 3D. Abaixo, o que cada um faz e com que conta.
O fundo da página
Pressão, isóbaras e vento geostrófico.
As linhas finas atrás do texto são isóbaras de um campo de pressão inventado, mas tratado como campo real: as setas que passam entre elas são o vento geostrófico calculado a partir do próprio gradiente desse campo.
O campo de pressão
Não há dado observado aqui. O campo é procedural: três oitavas de ruído de valor com interpolação suave, somadas a uma bacia quadrática que garante um centro de baixa e a uma depressão gaussiana que segue o ponteiro do mouse. O conjunto deriva lentamente, com período de 30 s.
ΔP = 4000 Pa por unidade de campo · 1 unidade de campo = 1000 km · σ = 180 px (raio do ponteiro) · s(t) é a força do ponteiro, relaxada exponencialmente ao entrar e sair.
O ruído de valor usa uma grade fixa de 64 × 64 valores pseudoaleatórios e interpola com a mesma smoothstep de sempre, o que dá continuidade de primeira derivada — condição necessária para o gradiente, e portanto o vento, não sair picotado.
Interpolação bilinear entre os quatro vértices da célula, com S aplicado em cada eixo.
As isóbaras
As linhas saem de marching squares sobre a grade amostrada do campo: até 32 níveis igualmente espaçados, desenhados numa única passada de path do canvas. Cada célula testa quais dos quatro vértices estão acima do nível e emite os segmentos correspondentes.
Interpolação linear na aresta entre os vértices a e b. Os dois casos ambíguos de sela (5 e 10) são resolvidos pela média dos quatro vértices da célula, e não por escolha fixa: é o que impede as linhas de se cruzarem.
Só os níveis que efetivamente cruzam a célula são percorridos — o laço vai do menor ao maior valor dos seus quatro vértices —, o que corta a maior parte do trabalho em regiões planas do campo.
O vento geostrófico
O vento geostrófico é o equilíbrio exato entre a força do gradiente de pressão e a força de Coriolis. É a aproximação de primeira ordem do escoamento em larga escala fora da camada limite, e é por isso que, num mapa sinótico, o vento sopra praticamente paralelo às isóbaras em vez de atravessá-las da alta para a baixa.
ρ = 1,225 kg·m⁻³ (densidade do ar ao nível do mar, atmosfera padrão). ug é a componente zonal, para leste; vg a meridional, para norte.
O parâmetro de Coriolis depende só da latitude escolhida para a cena — 30° S, o paralelo que corta o Sul do Brasil:
Ω = 7,292115 × 10⁻⁵ rad·s⁻¹ (velocidade angular da Terra) · φ = −30° · f ≈ −7,29 × 10⁻⁵ s⁻¹.
Como f < 0 no Hemisfério Sul, a circulação em torno de uma baixa sai no sentido horário — o contrário do que se vê na maior parte das animações prontas na internet, quase todas feitas para o Hemisfério Norte. Perto do equador o equilíbrio geostrófico simplesmente não vale: f → 0 e a velocidade diverge. O código verifica isso e devolve “sem vetor” em vez de inventar uma direção.
Diferenças centradas, precisão de segunda ordem, com h = 2 px e Δs = 10⁶ / escala do campo, em metros por pixel. O mesmo campo escalar alimenta as isóbaras e o gradiente, então linha e seta nunca discordam.
As setas que andam
As setas não são um campo estático: são parcelas lagrangianas, advectadas pelo vento amostrado na posição de cada uma, com integração de Euler explícita a cada quadro. Cada parcela vive 7 s, nasce em fase aleatória — para que os renascimentos não pulsem juntos — e reaparece se sair da tela.
G = 1,2 px·s⁻¹ por m·s⁻¹, ganho só de exibição: a 5000 m por pixel, o deslocamento real seria invisível. O comprimento desenhado da seta é proporcional a |Vg| e limitado por um teto visual, mas o vetor físico mantém a magnitude que a equação deu.
Como o canvas tem o eixo y apontando para baixo e o norte aponta para cima, o vetor de tela é (ug, −vg). O campo procedural está isolado numa única função: trocá-la por pressão ao nível do mar de um modelo numérico é o passo que transforma essa animação em um mapa de verdade.
O box de nuvens
Um cubo de 10 km, renderizado de dentro para fora.
Na página inicial há um cubo de 10 × 10 × 10 km com nuvens que nascem, crescem e se desfazem sobre um recorte de imagem de satélite. É WebGL2 puro, um triângulo de tela cheia e cinco shaders: sem three.js, sem modelo, sem textura de nuvem pronta.
1. O volume de ruído, assado uma vez
Antes do primeiro quadro, o programa gera uma textura 3D de 96³ pixels, camada por camada, e nunca mais volta a calculá-la. Ela guarda a forma-base das nuvens no canal vermelho e três frequências de detalhe nos demais.
w é ruído de Worley (distância ao ponto de célula mais próximo, invertida) e n é ruído de Perlin em grade periódica. A combinação Perlin–Worley é o que dá o aspecto de bolha coalescente em vez de mancha. remap(v,a,b,c,d) = c + (v−a)(d−c)/(b−a).
2. Onde há nuvem, e de que tipo
Duas amostras de baixa frequência formam um “mapa de tempo” em duas dimensões: cobertura e tipo. A cobertura corta o campo por limiar; o tipo interpola entre um gradiente vertical achatado, de estrato, e um alto e cheio, de cúmulo. A nuvem só existe entre 1200 m e 4600 m.
σ é o coeficiente de extinção, em unidades por metro. Uma segunda amostra de alta frequência erode as bordas, com o sinal invertido perto da base e mantido no topo — é o que dá pé chapado e topo encaracolado.
3. Transporte radiativo
Cada pixel lança um raio e integra a equação de transporte radiativo ao longo dele, com 88 passos. A transmitância segue Beer–Lambert; a integral de luz é resolvida analiticamente dentro de cada passo, e não por retângulo, o que mantém a energia conservada mesmo com passo grande.
Sem emissão: a nuvem não brilha, só espalha. O laço para quando T < 0,006 — abaixo disso, nada do que está atrás muda o pixel.
A direção do espalhamento vem de uma mistura de duas funções de fase de Henyey–Greenstein: um lóbulo dianteiro forte, responsável pelo brilho quando se olha a nuvem contra o sol, e um lóbulo traseiro fraco, responsável pelo cinza do lado sombreado.
θ é o ângulo entre o raio de visada e a direção do sol.
4. Múltiplo espalhamento, de mentirinha
Resolver o espalhamento múltiplo de verdade custaria ordens de grandeza mais. No lugar dele entra a aproximação por oitavas: a mesma luz direta é somada três vezes, cada uma com extinção, peso e anisotropia reduzidos. É o truque que faz o interior da nuvem ficar leitoso em vez de preto.
a = 0,52 (extinção), b = 0,48 (peso), c = 0,66 (anisotropia). O termo de “pó”, 1 − e−2,4 a σΔt, escurece as bordas iluminadas: é a correção empírica que devolve o contorno escuro que o modelo de espalhamento simples apaga.
A profundidade óptica até o sol, τsol, é medida com uma marcha curta de seis passos partindo do ponto atual, com passo crescendo 55 % a cada iteração e deslocamentos laterais em cone para amostrar volume em vez de linha, mais uma amostra distante que representa o resto da atmosfera.
5. Câmera, passos e ruído proposital
A câmera é em perspectiva: a origem do raio é a mesma em todo pixel e o que muda é a direção, aberta num cone a partir de um olho a 2,5 lados de distância do centro do box. É isso que faz a aresta próxima do terreno chegar mais larga que a distante — com a projeção ortográfica que havia antes as duas saíam iguais, e a leitura da profundidade se invertia. O enquadramento continua projetando os oito vértices do cubo e usando a maior extensão, agora com o fator de profundidade de cada um, senão os cantos do lado próximo — justamente os que a perspectiva alarga — sairiam do quadro. O tamanho aparente da cena é regulado pela distância do olho: aproximá-la abre mais o cone, afastá-la volta em direção ao ortográfico.
L = 10 000 m, H = meia-altura do quadro em metros, (u,v) as coordenadas normalizadas de tela. O passo cresce 2 % por iteração: o detalhe importa perto da câmera, não no fundo.
Duas decisões contra artefato: o início do raio recebe um deslocamento pseudoaleatório por pixel, o que troca as faixas concêntricas do passo fixo por um granulado que o desfoque some; e o percurso pula ao dobro do passo enquanto encontra vazio, recuando um passo assim que reencontra densidade.
6. A marca dentro da nuvem
A logo e os rótulos da rede não ficam por cima da cena: ficam dentro dela. Ao cruzar o plano da marca — perpendicular à visada e passando pelo hub —, a marcha fecha a camada da frente e recomeça uma nova. Sobram duas imagens, antes e depois do plano, e a composição encaixa a marca entre elas.
O mesmo critério de profundidade decide quais nós da rede são desenhados atrás da nuvem e quais na frente.
A nuvem é marchada em 480p, mas a marca, as arestas do cubo e a textura do solo são compostas na resolução do dispositivo. É o que permite texto nítido e nuvem barata no mesmo quadro. O desfoque é uma passada gaussiana separável aplicada só à nuvem.
7. Cor
A cena é calculada em luz linear e só no fim passa por um tone mapping de curva ACES aproximada. As imagens que entram na cena — o recorte de satélite, a marca — já vêm tonemapeadas e em sRGB, então o código aplica nelas a inversa analítica da curva antes de usá-las, para que não sejam iluminadas duas vezes.
A inversa sai da raiz da quadrática correspondente. A sombra que a nuvem projeta no solo vem de duas amostras de densidade na direção do sol, atenuadas por Beer–Lambert, e−45σ, calculada à parte do albedo para que a textura de satélite não passe pelo desfoque.
8. O que a rolagem controla
A elevação da câmera está presa à rolagem da página, com o meio da tela como linha de referência e o card como régua: enquanto sobrar mais de 80% do card abaixo dessa linha, a câmera fica a pino, em 90° — é o tempo de ver a cena parada antes de qualquer movimento. O tombo até 25° corre entre 80% e 50%, e depois fica preso no fim — a metade final do curso do card serve só para ler a cena já deitada. O azimute segue girando sozinho, e o arrasto do ponteiro continua livre para girar a cena. O ciclo de evolução da nuvem — cobertura, tipo e densidade se movendo juntos — vai e volta em triângulo suavizado a cada 30 s, porque em dente de serra o retorno ao mínimo apareceria como um salto.
O resto
E o que mais está rodando.
Fora as duas peças acima, a página é HTML, CSS e um arquivo de JavaScript. Sem framework, sem build, sem dependência remota além das fontes.
A abertura. O vídeo do hero começa ocupando a tela inteira, com a logo branca ao centro, e encolhe até virar o fundo do card. A transição espera o carregamento do render 3D — com teto de tempo, para que uma conexão ruim não prenda ninguém na tela cheia.
As entradas de seção. GSAP com ScrollTrigger, hospedado localmente, uma única vez por elemento e sempre com estado final visível caso o script falhe. Foco de teclado e a preferência por menos movimento cancelam a animação em curso em vez de competir com ela.
Acessibilidade. Tudo o que se move respeita prefers-reduced-motion: o campo de pressão desenha um quadro estático, o vídeo pausa e as entradas somem. As animações também param quando a aba sai de foco.
Desempenho. O campo de pressão roda a 30 quadros por segundo e só sobre a área visível, independentemente do comprimento do documento. O render 3D vive num iframe e carrega atrás da abertura, porque é a peça mais cara da página.
Referência para quem quiser ir atrás: o modelo de nuvem segue a linha do trabalho apresentado por Andrew Schneider e Nathan Vos para o Horizon Zero Dawn (SIGGRAPH 2015) e da aproximação de múltiplo espalhamento por oitavas de Magnus Wrenninge. O equilíbrio geostrófico está em qualquer livro de meteorologia dinâmica — o Holton é o de sempre.
Receber amostra em PDF