Skip to content

Demo 04 · Lab

A thing in space

A faceted metal object that catches coloured light on its edges, turns slowly, and leans toward your cursor.

Use this when

The background should be an object, something sculptural that belongs to your brand.

Skip it if: A shader field would do. Paying a heavy library to render what amounts to a gradient is the most common three.js mistake.

The prompt

Real 3D with three.js prompt
Add a 3D background to my hero section using three.js: a single dark metallic object floating behind the headline.

Requirements:
- One three.js scene on a full-viewport <canvas> behind the hero content.
- The object: an icosahedron with flat shading and a dark metallic standard material (deep navy base colour, metalness ~0.85, roughness ~0.3), bright enough that its silhouette reads even between light hits.
- Lighting: an ambient light strong enough to keep shadow sides visible, two coloured point lights, violet (#7C5CFF) upper-left, warm orange (#FF6A2A) lower-right, so opposite facets pick up opposite colours, and a faint cyan (#63E2FF) rim light behind the object so its edge always separates from the background.
- Note for three.js r155 and newer, where this scene will otherwise render as a black silhouette:
  - A metal has no diffuse response: it only shows what it reflects. With metalness ~0.85 and no environment, point lights alone leave the object invisible. Give the scene an environment: a 2x256 vertical gradient canvas texture, mapped as EquirectangularReflectionMapping, run through PMREMGenerator and assigned to scene.environment. That is a dozen lines and costs almost nothing.
  - Point-light intensity is now physical and falls off with the square of distance, so values written for older versions render almost black. Scale them up by roughly 50x and keep the ratios between the three lights.
- Atmosphere: light exponential fog in the page background colour, subtle enough to soften the far edges without swallowing the object.
- Motion: very slow continuous rotation on two axes plus a gentle vertical float. Add cursor parallax: the camera eases a small distance toward the pointer position (lerp it, never snap).
- Cap devicePixelRatio at 2, resize with the window, and pause the render loop when the tab is hidden.
- Respect prefers-reduced-motion: render one static frame, no rotation, no parallax.
- Keep the scene code itself under 3KB. Don't block first paint.

Performance notes

Technique
three.js scene
Scene code
3.3 KB
Library
three.js, 732 KB
Over the wire
182 KB gzipped
Device pixel ratio
Capped at 2
Reduced motion
Static frame, no parallax
Hidden tab
Render loop paused