Deep Ocean Explorer
2025Mundo submarino em tempo real no navegador com shaders GLSL escritos à mão para feixes de luz volumétricos, cáusticas e bioluminescência de medusas. Sistema de iluminação guiado por profundidade, 10 águas-vivas NPC com 8 padrões de migração e uma água-viva controlada pelo jogador com movimento 6-DOF.

Deep Ocean Explorer é um mundo 3D submarino interativo e ambiente rodando inteiramente no navegador. O jogador navega como uma água-viva por um oceano iluminado de forma procedural, populado por enxames de NPCs, cardumes, corais, algas e camadas de efeitos atmosféricos. Cada efeito visual — feixes de luz volumétricos, cáusticas, bioluminescência, névoa baseada em profundidade — é um ShaderMaterial GLSL escrito à mão sem dependências de biblioteca de pós-processamento. O projeto foi construído como uma demonstração de profundidade WebGL em tempo real.
A maioria das experiências 3D no navegador usa mapas de ambiente HDR e iluminação pré-assada para parecer boa. Essa abordagem parece fotorrealista, mas é passiva — a iluminação não responde à posição ou profundidade do jogador. O desafio era construir um mundo submarino onde cada sistema atmosférico (espalhamento de luz, cáusticas, névoa, bioluminescência) fosse totalmente dinâmico e guiado pela profundidade, mantendo a taxa de frames acima de 60fps em um laptop de nível médio.
Construir uma experiência 3D submarina em tempo real que demonstre: (1) autoria de shaders GLSL personalizados sem pipeline de pós-processamento; (2) sistema de iluminação dinâmica guiado por profundidade com transições suaves entre zonas; (3) comportamento de entidades NPC com máquina de estados; (4) movimento e interação do jogador; (5) renderização consciente de performance com tradeoffs documentados.
- ◈Desenvolvedor solo — autoria de shaders, arquitetura de cena, comportamento NPC, deploy
- 01Todos os shaders inline como template literals TypeScript — sem arquivos .glsl, sem pipeline de carregamento de shaders, sem falhas de compilação por assets faltando no GitHub Pages. Cada THREE.ShaderMaterial é definido dentro de hooks useMemo(), garantindo que os shaders sejam compilados uma vez e cacheados pela GPU.
- 02Derivadas dFdx/dFdy para cáusticas — em vez de uma segunda amostra de ruído para calcular o gradiente da superfície da água, as derivadas screen-space da GPU fornecem o gradiente exato do campo de ruído de graça. 1/(1 + dot(gradiente, gradiente) × 20) produz linhas de cáustica brilhantes nos picos de curvatura da superfície.
- 03Iluminação por profundidade como estrutura de dados — cinco zonas nomeadas (superfície, rasa, média, profunda, abismo) definem cor e intensidade de luz alvo. A cada frame, o sistema faz lerp dos valores atuais em direção ao alvo da zona ativa. Adicionar uma nova zona requer uma entrada de objeto, não nova lógica condicional.
- 04AdditiveBlending + depthWrite:false em todas as camadas de efeito — feixes volumétricos, cáusticas, raios divinos e partículas usam blending aditivo e pular a escrita de profundidade. Isso permite camadas ilimitadas de efeitos transparentes sem Z-fighting ou artefatos de overdraw.
- 05Posição do jogador como única fonte de verdade — o componente JellyfishCharacter propaga sua posição Three.js para Scene.tsx via callback onPositionChange, que a distribui para todos os 11 componentes downstream como props. Isso evita estado global enquanto garante que cada sistema sensível à profundidade receba a mesma fonte de verdade.
- 06Ambiente HDR substituído por iluminação customizada — o componente Environment do @react-three/drei (que busca HDR de um CDN remoto) causava erros 429 de rate-limit no GitHub Pages. Removê-lo e construir o DepthBasedLighting do zero eliminou a dependência externa e deu controle total sobre a gramática de iluminação.
- →Dependências de CDN remoto em deploys estáticos são um risco de confiabilidade — a falha no fetch do HDR era um bug de produção que só aparecia no GitHub Pages, não no desenvolvimento local. Substituí-lo por iluminação procedural foi tanto uma correção quanto uma feature: a iluminação ficou mais rica e controlável.
- →As derivadas screen-space (dFdx/dFdy) são subutilizadas em trabalhos WebGL criativos — fornecem gradientes matematicamente precisos sem custo de performance, permitindo simulação de cáusticas que de outra forma exigiria um ray-march completo.
- →Máquinas de estado de comportamento NPC precisam de aleatoriedade para parecer vivas — padrões determinísticos de água-viva pareciam robóticos. Adicionar ±20% de variação aleatória nas durações dos timers e 15% de probabilidade de mutação de padrão fez o enxame parecer orgânico.
- →Sistemas guiados por profundidade precisam de transições suaves, não limiares rígidos — versões iniciais tinham mudanças abruptas de iluminação nas fronteiras de zona. Mudar para lerp por frame eliminou o pop visual e fez a profundidade parecer uma variável contínua em vez de uma função degrau.
Ativo — publicado no GitHub Pages