VYBE シネマティック 3D は何をしますか?
HyperFrames 動画における 3D は、すべてのフレームが時間の純粋関数である <canvas> です。HyperFrames の three アダプターが時間を公開し、あなたがレンダリングします。権威: インストール後 /hyperframes-animation → adapters/three.md。
契約(譲歩不可)
- インポート固定:
import * as THREE from "https://cdn.jsdelivr.net/npm/[email protected]/+esm";(またはアドオン用に同じバージョンをピン留めするインポートマップ)。 - シーン、カメラ、レンダラー、マテリアルをロード時に同期的に構築し、レンダリングクリティカルなシークの前にモデルやテクスチャをロードします(Three の
DefaultLoadingManagerは自動的に待機されます。CPU 負荷の高いセットアップには、window.__hf.buildReady["<name>"] = promiseを登録してください)。 - 時間のみからレンダリング:
window.addEventListener("hf-seek", e => renderAt(e.detail.time)); renderAt(window.__hfThreeTime || 0); requestAnimationFrameループ、クロック、デルタ、未シードのMath.random()は禁止。renderer.setPixelRatio(1); renderer.setSize(W, H, false)とし、W/H はルート要素のdata-width/heightから取得。ルートにはdata-durationが必要。- 全面キャンバスに
data-layout-allow-overflowをマーク。
スケルトン
<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; // 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
// … 構築 …
function renderAt(t) { const p = t / D; /* カメラ+オブジェクトを t から */ renderer.render(scene, camera); }
window.addEventListener("hf-seek", (e) => renderAt(e.detail.time));
renderAt(window.__hfThreeTime || 0);
</script>
3D ワールドがシーンをまたがる場合(フィルム全体にわたるカメラアーク)はキャンバスをホスト(index.html)に配置し、1つのシーン内にのみ存在する場合はシーンファイルに配置します。その上に HTML タイプを重ね、DOM テキストで十分な場合は WebGL でテキストをレンダリングしないでください。
レシピ
- パーティクル / ダスト / 星:
THREE.Pointsとシード付きPRNGを使用した位置、パレットからの頂点カラー、丸いスプライト(CanvasTextureラジアルグラデーションをmapとして使用 — デフォルトのポイントは四角形)、AdditiveBlending、depthWrite: false。すべてのパーティクルをカメラの最も近いzより遠くに保ちます。そうしないと、カメラが通過するときに巨大なスプライトに膨らみます(実際のVYBEの欠陥)。 - ヒーローオーブ / 惑星:
SphereGeometry(r, 96, 64)+MeshStandardMaterial(metalness/roughness)+ エミッシブハローTorusGeometryリング。時間とともにライトアップします。 - ブラックホール: 暗い球体 + 降着円盤 =
RingGeometryとキャンバスグラデーションテクスチャ、70~80°傾けて回転。レンズリング = カメラに向いた2つ目の薄いトーラス。星のゆがみ = 背景ポイントレイヤーを中心付近で放射状にスケーリング。 - 分子: 原子位置の球体(多数の場合は
InstancedMesh)、それらの間の円柱(quaternion.setFromUnitVectorsで向きを設定)。カメラを周回させる。 - プロダクトターンテーブル:
GLTFLoader(インポートマップ)を使用した GLTF、作成されたクリップ用のAnimationMixer.setTime(t)、以下にスタジオライトリグ、ショット全体で20~35°の緩やかな軌道。 - データ彫刻: データから高さが決まる
InstancedMeshボックス。時間の経過とともにsmoothstepで成長します。 - プロシージャル地形 / 波:
PlaneGeometryを JS でtから変形(最大40k頂点のフレームごとに位置を再計算)、またはShaderMaterialでrenderAtに設定されたuTimeユニフォームを使用。
ライティング
references/lighting.md を読み込んでください。最小限のリグ: キーライト(Point/Directional)、対照的な色相のリム/バックライト、および HemisphereLight フィル — 1つのライトだけのメッシュは暗い側が黒い切り抜きとしてレンダリングされます。ライトの強度を同じ時間関数から固定比率で駆動します。
カメラ
正規化された進行度 p = t / D から位置を導出し、アクトごとにスムーズステップセグメントを使用します(シネマティックテンプレートの renderAt を参照)。カットの場合、const CUT_B = 23 を一度宣言し、それをカメラショットセレクターとオブジェクトの可視性の両方に使用します。直前と直後のフレームを確認してください(snapshot --at 22.9667,23)。
パフォーマンス(ヘッドレス Chrome はソフトウェア GL の場合があります)
- 最大100kトライアングル、最大20kパーティクル、フレーム履歴を必要とするポストプロセッシングパスはなし。ブルーム: 加法的スプライト/ハローで偽装します。
- 低RAMマシンでの4Kでの
antialias+ 巨大なキャンバスを避け、ドラフトレンダリングをテストします。 - レンダリング環境で WebGL が失敗した場合、キャンバスは黒くなります: QC が黒フレームとして検出します。シーンの 2D キャンバスまたは CSS-3D バージョンにフォールバックします。