Three.js Depth Portrait

Recreate the interactive depth portrait effect popularized by modern portfolio websites using Three.js and WebGL.

View the Project on GitHub flavioow/threejs-depth-portrait

Improving The Experience

At this point, the effect can render and react to input. The next step is to make it feel better.

The experience improves through motion smoothing, loading states and small responsive adjustments.

Smooth The Motion

Raw input changes too quickly. If the shader used raw cursor or gyro values directly, the effect would feel nervous.

damped-motion.ts creates a small motion system with two values:

Each frame, current moves toward target using damping. This creates a more natural delay and makes the portrait feel less mechanical.

Update Motion In The Scene

SceneRoot owns the damped motion state.

Inside useFrame, it:

CameraController and ImagePlane both use the smoothed value, which keeps camera motion and shader motion in sync.

Add Loading State

The scene depends on texture loading, and the page depends on browser readiness. The loader should wait for both.

The loading system is split into:

This keeps the first impression controlled instead of showing a half-loaded scene.

Add Responsive Adjustment

useBreakpoint helps adjust the portrait position and scale by viewport size.

The current project uses it inside ImagePlane to move the portrait slightly on mobile and keep the framing pleasant across screen sizes.

Checkpoint

Before moving on, the page should:

Next: Finishing