Hero buraco negro 3D (R3F) · pós-processamento de cinema
NEXUS Loja Geek
Problema
Marcas geek e gamer precisam de uma vitrine com cara de produto premium, com impacto visual que diferencia da concorrência.
Solução
Vitrine conceitual com hero de buraco negro estilo Interestelar (React Three Fiber): disco de acreção turbulento, distorção gravitacional, planeta e asteroides, iluminação HDRI e pós-processamento cinematográfico. Uma timeline (Theatre.js) faz a câmera mergulhar no buraco conforme o scroll.
Como foi construído
O hero não usa nenhum asset de buraco-negro pronto: é um shader GLSL escrito à mão (BlackHoleScene.jsx) rodando num único plano dentro do React Three Fiber. FBM (fractal Brownian motion) gera a turbulência do disco de acreção em duas camadas de ruído, um perfil radial separa disco fino de núcleo, e o anel de fóton e o "efeito Doppler" (lado que se aproxima mais claro) são somados por cima, tudo calculado por pixel e sem textura. Sobre isso soma-se um planeta com atmosfera em fresnel aditivo e um campo de asteroides via instancedMesh (38 instâncias, uma única draw call) girando com ruído próprio de rotação.
A distorção gravitacional é um efeito de pós-processamento próprio, não um filtro pronto: uma classe LensingEffect que estende Effect da lib postprocessing e é conectada ao pipeline do R3F via wrapEffect. O shader da lente desloca o UV de amostragem do frame inteiro em função da distância ao horizonte de eventos (deflexão ~1/d²), curvando estrelas e nebulosa ao redor do buraco como uma lente de Einstein real. A câmera, por sua vez, não segue o scroll diretamente. Uma timeline do Theatre.js (heroSheet, com keyframes de posição e FOV salvos em theatre-state.json) é 'esfregada' (sequence.position = t * SEQ_LEN) proporcionalmente ao scrollY, e o resultado é suavizado com lerp antes de aplicar à câmera. É o que dá o mergulho cinematográfico no buraco sem depender de nenhuma lib de scroll externa.
Custo de GPU é tratado como orçamento, não como detalhe. O dpr é limitado a [0.75, 1], o antialiasing fica desligado (compensado pelo bloom e pelo noise do pós-processamento), e um IntersectionObserver no wrapper do Canvas alterna frameloop entre 'always' e 'never'. Assim que o hero sai da viewport, o R3F para de renderizar frames por completo, em vez de só ficar invisível consumindo GPU no resto do scroll. É o mesmo raciocínio de performance que se aplicaria a um dashboard com gráficos pesados: renderizar só o que está de fato na tela.
Abaixo do hero, a loja é dados puros e componentes sem backend. Seis catálogos (heróis, quadrinhos, séries, games, setup, gear) vivem em src/data/products.js como arrays simples, e o ProductCard resolve a imagem numa cadeia de fallback resiliente: tenta a foto real (.jpg, depois .png se a primeira falhar), cai pro emblema vetorial do herói se não houver foto, e cai pra um visual SVG procedural (hexágono, núcleo e partículas, gerado pela accent color) se nem isso existir. Nenhum card quebra por imagem ausente. A seção de Games tem filtro client-side por categoria (cat) reconstruindo o carrossel (key={filter} força reentrada animada), e toda a UI tem som: bips procedurais via WebAudio (useSound.js) sem nenhum arquivo de áudio, com AudioContext criado sob demanda no primeiro gesto do usuário, que é o jeito de contornar as autoplay policies dos navegadores.
Buraco negro em GLSL puro
Disco de acreção, anel de fóton e núcleo calculados por pixel com FBM, sem nenhuma textura.
Lente gravitacional custom
Effect de pós-processamento próprio (deflexão ~1/d²) que curva estrelas e nebulosa ao redor do horizonte de eventos.
Câmera scrubbed por Theatre.js
Scroll da página esfrega uma timeline de câmera keyframada, sem lib de scroll externa.
GPU sob orçamento
IntersectionObserver desliga o frameloop do R3F fora da viewport; dpr limitado e antialiasing off.
Mais telas
Stack
- React
- Vite
- Three.js · R3F
- react-postprocessing
- Theatre.js
- GLSL


