Skip to content

3D — Scene3D & extrude

ONDA’s 3D is the mograph core of “3D” — camera fly-throughs, card walls, parallax, exploded UI, billboard text, and lit extruded logos — not a general game engine. It comes in two parts: 3D layers (flat planes in a shared perspective world) and extruded solids (2D outlines pushed into lit 3D meshes).

Wrap content in <Scene3D>. Its direct children become 3D layers in one shared world, viewed through a perspective camera. Each layer is its rendered 2D content placed by position3d and tilted by rotation3d, then depth-sorted and composited.

import { Scene3D, Group, Text, Image } from 'onda-engine/react'
<Scene3D camera={{ position: [0, 0, -800], target: [0, 0, 0], fov: 50 }}>
<Image src="/card-a.jpg" position3d={[-300, 0, 0]} rotation3d={[0, 25, 0]} />
<Image src="/card-b.jpg" position3d={[ 300, 0, 0]} rotation3d={[0, -25, 0]} />
<Text position3d={[0, 0, -200]}>Front and centre</Text>
</Scene3D>

z = 0 is the framing plane — a layer at z = 0 with no rotation renders pixel-identical to its 2D placement. Larger z is farther into the screen (smaller); negative z is nearer the camera. This follows the After Effects convention. Because of the invariant, wrapping existing content in <Scene3D> changes nothing until you actually move layers in z.

These live on any node (NodeProps) and are meaningful only inside a <Scene3D>:

  • position3d={[x, y, z]} — world position in px. Layers without it sit at z = 0.
  • rotation3d={[x, y, z]} — degrees, applied Z·Y·X: X pitch (tilt toward/away), Y yaw (swing), Z roll (in-plane spin).
  • anchor3d={[x, y]} — the pivot within the layer’s content plane that position/rotation act about (default: the layer’s centre).

Animate position3d / rotation3d per frame for fly-throughs, parallax, and exploded views; animate the camera for camera moves.

Inside a <Scene3D>, give a shape, path, or text layer an extrude and its 2D outline becomes a real lit 3D mesh with thickness and side walls, shaded by a directional light so it catches the light as it rotates — the classic “3D logo / title”.

<Scene3D camera={{ position: [0, 0, -700] }}>
<Text extrude={60} rotation3d={[0, 35, 0]} fontWeight={800}>ONDA</Text>
<Path d="M…" extrude={{ depth: 40 }} fill="#d96b82" />
</Scene3D>

Text faces come from the glyph outlines (skrifa); shape/path faces are tessellated (lyon).

CapabilityVello (GPU)CPU reference / live preview
<Scene3D> layers, position3d, depth sort✅ true perspective✅ 2.5D depth-sorted (per-layer distance scale)
rotation3d out-of-plane tilt— (flat)
extrude lit solids✅ shaded mesh— (flat outline)