VYBE Cinematic 3D
3D em um vídeo HyperFrames é um <canvas> cujo cada quadro é uma função pura
do tempo. O adaptador three do HyperFrames publica o tempo; você o renderiza.
Autoridade: /hyperframes-animation → adapters/three.md quando instalado.
Contrato (innegociável)
- Importação fixa:
import * as THREE from "https://cdn.jsdelivr.net/npm/[email protected]/+esm";(ou um importmap que fixe a mesma versão para complementos). - Construa cena, câmera, renderizador, materiais sincronamente no carregamento; carregue qualquer
modelo/textura antes da busca crítica para renderização (o
DefaultLoadingManagerdo Three é aguardado automaticamente). Para configuração pesada de CPU, registrewindow.__hf.buildReady["<name>"] = promise. - Renderize apenas a partir do tempo:
window.addEventListener("hf-seek", e => renderAt(e.detail.time)); renderAt(window.__hfThreeTime || 0); - Sem loops
requestAnimationFrame, clocks, deltas ouMath.random()não seedado. renderer.setPixelRatio(1); renderer.setSize(W, H, false)com W/H dodata-width/heightda raiz. A raiz deve terdata-duration.- Marque o canvas de sangria total com
data-layout-allow-overflow.
Esqueleto
<canvas id="gl" width="1920" height="1080" data-layout-allow-overflow></canvas>
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/[email protected]/+esm";
const root = document.getElementById("vybe-root");
const W = +root.dataset.width, H = +root.dataset.height, D = +root.dataset.duration;
const css = getComputedStyle(document.documentElement);
const tok = (n, f) => css.getPropertyValue(n).trim() || f; // lê tokens VYBE
const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById("gl"), antialias: true });
renderer.setPixelRatio(1); renderer.setSize(W, H, false);
renderer.setClearColor(new THREE.Color(tok("--vy-bg", "#000")), 1);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(W > H ? 40 : 60, W / H, 0.1, 200); // FOV mais amplo em retrato
// … construa …
function renderAt(t) { const p = t / D; /* câmera + objetos a partir de t */ renderer.render(scene, camera); }
window.addEventListener("hf-seek", (e) => renderAt(e.detail.time));
renderAt(window.__hfThreeTime || 0);
</script>
Coloque o canvas no hospedeiro (index.html) quando o mundo 3D abranger cenas
(arco de câmera através do filme); coloque-o em um arquivo de cena apenas quando ele viver em uma única cena.
Sobreponha HTML acima dele; nunca renderize texto em WebGL quando o texto DOM resolver.
Receitas
- Partículas / poeira / estrelas:
THREE.Pointscom um PRNG seedado para posições, cores de vértice da paleta, um sprite redondo (CanvasTexturegradiente radial comomap) — pontos padrão são quadrados —AdditiveBlending,depthWrite: false. Mantenha cada partícula além do z mais próximo da câmera, ou ela infla em um sprite gigante quando a câmera a ultrapassa (um defeito real do VYBE). - Orbe / planeta herói:
SphereGeometry(r, 96, 64)+MeshStandardMaterial(metalness/roughness) + halo emissivoTorusGeometryanel; ilumine-o ao longo do tempo. - Buraco negro: esfera escura + disco de acreção =
RingGeometrycom uma textura de gradiente de canvas, inclinado 70–80°, girando; anel de lente = segundo toro fino voltado para a câmera; estrelas curvadas = escale uma camada de pontos de fundo radialmente perto do centro. - Molécula: esferas nas posições dos átomos (
InstancedMeshpara muitas), cilindros entre eles (oriente comquaternion.setFromUnitVectors); órbita da câmera. - Mesa giratória de produto: GLTF via
GLTFLoader(importmap),AnimationMixer.setTime(t)para clipes autorados; rig de luz de estúdio abaixo; órbita lenta 20–35° sobre o take. - Escultura de dados:
InstancedMeshcaixas cujas alturas vêm dos dados, crescidas comsmoothstepao longo do tempo. - Terreno/ondas procedurais: desloque um
PlaneGeometryem JS a partir det(recalcule posições por quadro para ≤40k vértices) ou em umShaderMaterialcom um uniformeuTimedefinido emrenderAt.
Iluminação
Carregue references/lighting.md. Rig mínimo: chave (Point/Directional), luz de contraste/traseira
em um matiz contrastante e um HemisphereLight de preenchimento — uma malha iluminada com apenas
uma luz renderiza como um recorte preto em seu lado escuro. Conduza as intensidades das luzes a partir da
mesma função de tempo em proporções fixas.
Câmera
Derive a posição do progresso normalizado p = t / D com segmentos smoothstep por
ato (veja o template cinematográfico renderAt). Para cortes, declare const CUT_B = 23
uma vez e use-o tanto para o seletor de take da câmera quanto para a visibilidade dos objetos; verifique os
quadros imediatamente antes e depois (snapshot --at 22.9667,23).
Desempenho (Chrome headless pode ser GL de software)
- ≤ 100k triângulos, ≤ 20k partículas, sem passes de pós-processamento que precisem de histórico de quadro. Bloom: simule-o com sprites/halos aditivos.
- Evite
antialias+ canvases enormes em 4K em máquinas com pouca RAM; teste uma renderização de rascunho. - Se o WebGL falhar no ambiente de renderização, o canvas fica preto: o controle de qualidade o detecta como quadros pretos; recorra a um canvas 2D ou versão CSS-3D da cena.