Skip to main content
Three.js is a powerful 3D graphics library built on WebGL. Helios provides precise frame control for rendering Three.js scenes to video.

Basic setup

Three.js requires manual rendering driven by Helios instead of using requestAnimationFrame.

React Three Fiber integration

For React applications, use @react-three/fiber with Helios controlling the frame loop.

Scene component

Critical patterns

Disable automatic rendering

Three.js and React Three Fiber both have built-in render loops. You must disable them:
  • Vanilla Three.js: Don’t call requestAnimationFrame or renderer.setAnimationLoop()
  • React Three Fiber: Set frameloop="never" on the <Canvas> component

Use Helios time, not system time

Always calculate animations from state.currentFrame / fps instead of Date.now() or performance.now():

Handle resize properly

Update camera aspect ratio and renderer size on window resize:

Performance considerations

WebGL context limits

Browsers limit the number of WebGL contexts. Destroy renderers when unmounting:

Scene complexity

Three.js performance depends on:
  • Polygon count: Keep meshes under 100k triangles for smooth rendering
  • Draw calls: Merge geometries to reduce draw calls
  • Texture size: Use power-of-2 textures (512x512, 1024x1024) for GPU efficiency
  • Lighting: Limit real-time shadows and use baked lighting where possible

Rendering resolution

Match the renderer size to your target export resolution:
Higher resolutions increase render time proportionally.

Frame rate vs quality

Lower FPS reduces total render time but may affect motion smoothness:
  • 30 fps: Standard for most content, good balance
  • 60 fps: Smooth motion, doubles render time
  • 24 fps: Cinematic feel, fastest render

Package dependencies

For React Three Fiber:

Common issues

Black screen on render

Ensure you have lighting in your scene:

Animation not playing

Verify Helios is bound to the document timeline:
And that you’re subscribing to state changes:

Canvas not resizing

Update both camera and renderer on resize events: