Skip to main content
Impact: MEDIUM - Enables proper 3D scene setup and smooth animations
This skill covers integrating Three.js with Remotion using ThreeCanvas, including proper lighting, camera setup, and frame-based animations.

ThreeCanvas Setup

Always wrap 3D content in ThreeCanvas and include proper lighting.
<mesh rotation={[0, frame * 0.02, 0]}>
  <boxGeometry args={[2, 2, 2]} />
  <meshStandardMaterial color="#4a9eff" />
</mesh>
Without ThreeCanvas, Three.js components will not render. It sets up the WebGL renderer and scene context.

Lighting Setup

Every 3D scene needs ambient + directional light for depth.
<ThreeCanvas>
  <mesh>
    <sphereGeometry args={[1, 32, 32]} />
    <meshStandardMaterial color="red" />
  </mesh>
</ThreeCanvas>
  • ambientLight: Provides base illumination, prevents pure black shadows
  • directionalLight/pointLight: Creates highlights and shadows, gives depth
Without both, 3D objects look flat or completely black.

Light Types

Uniform lighting from all directions.
<ambientLight intensity={0.4} />
Use for: Base lighting, preventing pure black areasIntensity: 0.3-0.6 typical range
Parallel rays from a direction (like sunlight).
<directionalLight position={[5, 5, 5]} intensity={0.8} />
Use for: Main light source, creating shadowsIntensity: 0.5-1.0 typical range
Light emanating from a point in all directions.
<pointLight position={[10, 10, 10]} intensity={1.0} />
Use for: Localized lighting, dramatic effectsIntensity: 0.8-2.0 typical range
Cone of light pointing in a direction.
<spotLight 
  position={[10, 10, 5]} 
  angle={0.3} 
  intensity={1.0}
/>
Use for: Focused lighting, stage effects

Frame-Based Rotation

Use frame directly for smooth continuous rotation.
const frame = useCurrentFrame();
const rotationY = frame * 0.02; // Adjust speed with multiplier

<mesh rotation={[0, rotationY, 0]}>
  <boxGeometry args={[2, 2, 2]} />
  <meshStandardMaterial color="#4a9eff" />
</mesh>;
Rotation values are in radians. Multiply frame by small values (0.01-0.05) for smooth rotation. Higher values spin faster.

Floating/Hovering Animation

Use sine wave on Y position for organic floating effect.
const frame = useCurrentFrame();
const floatY = Math.sin(frame * 0.1) * 0.3; // Amplitude 0.3, speed 0.1

<mesh position={[0, floatY, 0]}>{/* geometry and material */}</mesh>;
Math.sin(frame * speed) * amplitude
  • speed (0.1): How fast it oscillates. Higher = faster bounce
  • amplitude (0.3): How far it moves. Higher = larger motion
At 30fps:
  • speed: 0.1 = ~5 second cycle
  • speed: 0.2 = ~2.5 second cycle

Spring-Based Scale Entrance

Use spring() for bouncy 3D object entrances.
const scaleProgress = spring({
  frame,
  fps,
  config: { damping: 12, stiffness: 100 },
});

<mesh scale={[scaleProgress, scaleProgress, scaleProgress]}>
  {/* geometry and material */}
</mesh>;
Apply the same scale value to all three axes (X, Y, Z) for uniform scaling. Use different values for squash/stretch effects.

Camera Positioning

Position camera at reasonable distance for scene visibility.
<ThreeCanvas camera={{ position: [0, 0, 5], fov: 75 }}>
  {/* scene content */}
</ThreeCanvas>
[x, y, z] coordinates in 3D space.
position: [0, 0, 5]  // 5 units back from origin
position: [3, 2, 5]  // offset right and up
Typical values: Z distance of 3-10 units
Camera viewing angle in degrees.
fov: 45  // Narrow, telephoto
fov: 75  // Standard, natural
fov: 90  // Wide angle
Default: 75 degrees (good starting point)

Common Geometries

<boxGeometry args={[width, height, depth]} />
Example:
<boxGeometry args={[2, 2, 2]} /> // 2x2x2 cube

Materials

<meshStandardMaterial 
  color="#4a9eff" 
  metalness={0.5} 
  roughness={0.2}
/>
meshStandardMaterial is the most realistic and works best with proper lighting. meshBasicMaterial doesn’t respond to lights and is useful for flat-shaded objects or debugging.

Key Patterns

1

Setup ThreeCanvas

<ThreeCanvas camera={{ position: [0, 0, 5], fov: 75 }}>
2

Add Lighting

<ambientLight intensity={0.4} />
<directionalLight position={[5, 5, 5]} intensity={0.8} />
3

Create Mesh

<mesh rotation={[0, frame * 0.02, 0]}>
  <boxGeometry args={[2, 2, 2]} />
  <meshStandardMaterial color="#4a9eff" />
</mesh>
4

Animate with frame

rotation={[0, frame * 0.02, 0]}
position={[0, Math.sin(frame * 0.1) * 0.3, 0]}

Common Mistakes to Avoid

Don’t forget ThreeCanvas - Three.js components must be wrapped in <ThreeCanvas> or they won’t render.
Don’t skip lighting - Without lights, meshStandardMaterial objects appear black. Always add ambientLight + directionalLight.
Don’t use degrees for rotation - Three.js uses radians. 360° = 2 * Math.PI radians.
Don’t position camera at origin - If camera is at [0, 0, 0], it’s inside objects. Move it back on Z-axis: [0, 0, 5].

Advanced: Animated Camera

const frame = useCurrentFrame();
const cameraZ = interpolate(frame, [0, 60], [10, 5]);
const cameraY = Math.sin(frame * 0.05) * 2;

<ThreeCanvas 
  camera={{ 
    position: [0, cameraY, cameraZ], 
    fov: 75 
  }}
>
  {/* scene */}
</ThreeCanvas>
Animating the camera creates cinematic movement. Combine position changes with rotation for orbit effects.

Spring Physics

Add bounce to 3D objects

Sequencing

Coordinate multiple 3D elements

Build docs developers (and LLMs) love