three

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Three.js for HyperFrames

适用于HyperFrames的Three.js

HyperFrames supports Three.js through its
three
runtime adapter. The adapter does not own your scene. It publishes HyperFrames time and dispatches a seek event so your composition can render the exact frame.
HyperFrames通过其
three
运行时适配器支持Three.js。该适配器不会接管你的场景。它会发布HyperFrames时间并分发seek事件,以便你的合成内容可以渲染精确的帧。

Contract

约定

  • Create the scene, camera, renderer, materials, and assets synchronously when possible.
  • Render from HyperFrames time, not wall-clock time.
  • Listen for the
    hf-seek
    event and render exactly that time.
  • Load models, textures, and HDRIs before render-critical seeking. Do not fetch them at seek time.
  • Avoid
    requestAnimationFrame
    or
    renderer.setAnimationLoop
    as the source of truth for render-critical motion.
The adapter sets
window.__hfThreeTime
and dispatches
new CustomEvent("hf-seek", { detail: { time } })
on each seek.
  • 尽可能同步创建场景、相机、渲染器、材质和资源。
  • 基于HyperFrames时间进行渲染,而非挂钟时间。
  • 监听
    hf-seek
    事件并精确渲染该时间点的内容。
  • 在渲染关键的seek操作前加载模型、纹理和HDRI。不要在seek时获取它们。
  • 避免将
    requestAnimationFrame
    renderer.setAnimationLoop
    作为渲染关键运动的事实来源。
适配器会设置
window.__hfThreeTime
,并在每次seek时分发
new CustomEvent("hf-seek", { detail: { time } })

Basic Pattern

基础模式

html
<canvas id="three-layer"></canvas>
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.181.2/+esm";

  const canvas = document.getElementById("three-layer");
  const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
  // Match these to your composition's frame size.
  renderer.setSize(1920, 1080, false);
  renderer.setPixelRatio(1);

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(35, 1920 / 1080, 0.1, 100);
  camera.position.set(0, 0, 6);

  const mesh = new THREE.Mesh(
    new THREE.IcosahedronGeometry(1.4, 4),
    new THREE.MeshStandardMaterial({ color: 0x64d2ff, roughness: 0.38 }),
  );
  scene.add(mesh);
  scene.add(new THREE.HemisphereLight(0xffffff, 0x223344, 2));

  function renderAt(time) {
    mesh.rotation.y = time * 0.7;
    mesh.rotation.x = Math.sin(time * 0.6) * 0.16;
    renderer.render(scene, camera);
  }

  window.addEventListener("hf-seek", (event) => {
    renderAt(event.detail.time);
  });

  renderAt(window.__hfThreeTime || 0);
</script>
css
#three-layer {
  width: 100%;
  height: 100%;
  display: block;
}
html
<canvas id="three-layer"></canvas>
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.181.2/+esm";

  const canvas = document.getElementById("three-layer");
  const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
  // Match these to your composition's frame size.
  renderer.setSize(1920, 1080, false);
  renderer.setPixelRatio(1);

  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(35, 1920 / 1080, 0.1, 100);
  camera.position.set(0, 0, 6);

  const mesh = new THREE.Mesh(
    new THREE.IcosahedronGeometry(1.4, 4),
    new THREE.MeshStandardMaterial({ color: 0x64d2ff, roughness: 0.38 }),
  );
  scene.add(mesh);
  scene.add(new THREE.HemisphereLight(0xffffff, 0x223344, 2));

  function renderAt(time) {
    mesh.rotation.y = time * 0.7;
    mesh.rotation.x = Math.sin(time * 0.6) * 0.16;
    renderer.render(scene, camera);
  }

  window.addEventListener("hf-seek", (event) => {
    renderAt(event.detail.time);
  });

  renderAt(window.__hfThreeTime || 0);
</script>
css
#three-layer {
  width: 100%;
  height: 100%;
  display: block;
}

AnimationMixer Pattern

AnimationMixer模式

For GLTF or authored clip animation, seek the mixer directly:
js
function renderAt(time) {
  mixer.setTime(time);
  renderer.render(scene, camera);
}
If several mixers exist, seek all of them from the same
time
.
对于GLTF或制作好的片段动画,直接seek混合器:
js
function renderAt(time) {
  mixer.setTime(time);
  renderer.render(scene, camera);
}
如果存在多个混合器,请从同一
time
对所有混合器执行seek操作。

Good Uses

适用场景

  • Deterministic 3D objects, product spins, particles with seeded data, and shader plates.
  • Camera moves derived from
    time
    .
  • GLTF animation clips when assets are local and loaded before validation completes.
  • 确定性3D对象、产品旋转、带种子数据的粒子以及着色器模板。
  • 基于
    time
    生成的相机移动。
  • 资源为本地且在验证完成前已加载的GLTF动画片段。

Avoid

注意事项

  • Using
    Date.now()
    ,
    performance.now()
    , or clock deltas to update scene state.
  • Leaving render-critical work inside a free-running animation loop.
  • Loading remote models or textures at render time.
  • Device-pixel-ratio dependent output. Pin renderer size and pixel ratio for video renders.
  • Post-processing passes that depend on previous frame history unless you can reconstruct state from time.
  • 避免使用
    Date.now()
    performance.now()
    或时钟增量来更新场景状态。
  • 不要将渲染关键工作留在自由运行的动画循环中。
  • 不要在渲染时加载远程模型或纹理。
  • 避免依赖设备像素比的输出。为视频渲染固定渲染器尺寸和像素比。
  • 除非你能从时间重建状态,否则避免依赖前一帧历史的后期处理通道。

Validation

验证

After editing a Three.js composition:
bash
npx hyperframes lint
npx hyperframes validate
编辑Three.js合成内容后:
bash
npx hyperframes lint
npx hyperframes validate

Credits And References

致谢与参考