VYBE Cinematic 3D
La 3D dans une vidéo HyperFrames est un <canvas> dont chaque image est une fonction pure
du temps. L'adaptateur three d'HyperFrames publie le temps ; vous le rendez.
Autorité : /hyperframes-animation → adapters/three.md une fois installé.
Contrat (non négociable)
- Import verrouillé :
import * as THREE from "https://cdn.jsdelivr.net/npm/[email protected]/+esm";(ou une importmap verrouillant la même version pour les modules complémentaires). - Construire la scène, la caméra, le moteur de rendu, les matériaux de manière synchrone au chargement ; charger tout
modèle/texture avant la recherche critique pour le rendu (le
DefaultLoadingManagerde Three est attendu automatiquement). Pour une configuration CPU lourde, enregistrerwindow.__hf.buildReady["<nom>"] = promise. - Rendre uniquement à partir du temps :
window.addEventListener("hf-seek", e => renderAt(e.detail.time)); renderAt(window.__hfThreeTime || 0); - Pas de boucles
requestAnimationFrame, d'horloges, de deltas ou deMath.random()non ensemencée. renderer.setPixelRatio(1); renderer.setSize(W, H, false)avec W/H provenant dudata-width/heightde la racine. La racine doit avoirdata-duration.- Marquer le canvas plein écran
data-layout-allow-overflow.
Squelette
<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; // lire les 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 plus large en portrait
// … construire …
function renderAt(t) { const p = t / D; /* caméra + objets à partir de t */ renderer.render(scene, camera); }
window.addEventListener("hf-seek", (e) => renderAt(e.detail.time));
renderAt(window.__hfThreeTime || 0);
</script>
Placer le canvas dans le hôte (index.html) lorsque le monde 3D s'étend sur plusieurs scènes
(arc de caméra à travers le film) ; le placer dans un fichier de scène uniquement lorsqu'il vit dans une seule scène.
Superposer le type HTML au-dessus ; ne jamais rendre de texte en WebGL lorsque le texte DOM suffit.
Recettes
- Particules / poussière / étoiles :
THREE.Pointsavec un PRNG ensemencé pour les positions, couleurs de sommets issues de la palette, un sprite rond (CanvasTexturegradient radial commemap) — les points par défaut sont carrés —AdditiveBlending,depthWrite: false. Garder chaque particule au-delà du z le plus proche de la caméra, sinon elle se transforme en un sprite géant lorsque la caméra la dépasse (un vrai défaut VYBE). - Orbe héroïque / planète :
SphereGeometry(r, 96, 64)+MeshStandardMaterial(metalness/roughness) + halo émissif anneauTorusGeometry; l'éclairer au fil du temps. - Trou noir : sphère sombre + disque d'accrétion =
RingGeometryavec une texture de gradient de canvas, inclinée de 70 à 80°, en rotation ; anneau de lentille = second tore fin face à la caméra ; étoiles courbées = mettre à l'échelle une couche de points d'arrière-plan radialement près du centre. - Molécule : sphères aux positions des atomes (
InstancedMeshpour beaucoup), cylindres entre elles (orienter avecquaternion.setFromUnitVectors) ; orbite de la caméra. - Présentation produit : GLTF via
GLTFLoader(importmap),AnimationMixer.setTime(t)pour les clips créés ; éclairage de studio ci-dessous ; orbite lente de 20 à 35° sur le plan. - Sculpture de données :
InstancedMeshboîtes dont les hauteurs proviennent des données, agrandies avecsmoothstepau fil du temps. - Terrain/vagues procédurales : déplacer un
PlaneGeometryen JS à partir det(recalculer les positions par image pour ≤40k sommets) ou dans unShaderMaterialavec une uniformeuTimedéfinie dansrenderAt.
Éclairage
Charger references/lighting.md. Éclairage minimum : clé (Point/Directional), contre-jour/arrière
lumineux dans une teinte contrastée, et un HemisphereLight de remplissage — un maillage éclairé avec seulement
une lumière rend une silhouette noire sur son côté sombre. Piloter les intensités lumineuses à partir de la même
fonction temporelle avec des ratios fixes.
Caméra
Dériver la position de la progression normalisée p = t / D avec des segments smoothstep par
acte (voir le renderAt du modèle cinématographique). Pour les coupes, déclarer const CUT_B = 23
une fois et l'utiliser à la fois pour le sélecteur de plan de caméra et la visibilité des objets ; vérifier les
images juste avant et après (snapshot --at 22.9667,23).
Performance (Chrome headless peut utiliser OpenGL logiciel)
- ≤ 100k triangles, ≤ 20k particules, aucune passe de post-processing nécessitant un historique d'images. Bloom : le simuler avec des sprites/halos additifs.
- Éviter
antialias+ des canvas énormes en 4K sur des machines à faible RAM ; tester un rendu préliminaire. - Si WebGL échoue dans l'environnement de rendu, le canvas est noir : le contrôle qualité le détecte comme des images noires ; utiliser un canvas 2D ou une version CSS-3D de la scène en secours.