threejs-impl-drei

Installation
SKILL.md

threejs-impl-drei

Quick Reference

Installation

npm install @react-three/drei @react-three/fiber three

Critical Warnings

ALWAYS wrap components that use loader hooks (useGLTF, useTexture, useFBX, useKTX2, useFont) in <Suspense fallback={...}>. Omitting Suspense causes the entire React tree to crash.

ALWAYS add makeDefault to your primary camera controls (<OrbitControls makeDefault />). Without makeDefault, Drei controls do NOT integrate with R3F's event system and pointer events break.

NEVER use an invalid Environment preset name. The ONLY valid presets are: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse.

NEVER forget to call .preload() for critical assets. Use useGLTF.preload('/model.glb') at module scope to start loading before component mount.

ALWAYS use <Instances> for rendering more than 100 identical meshes. Individual meshes cause one draw call each; instances batch them into one.


Controls

OrbitControls

The most common camera control. Orbit, zoom, and pan around a target.

import { OrbitControls } from '@react-three/drei'

<OrbitControls
  makeDefault           // ALWAYS add — integrates with R3F events
  enableDamping         // smooth movement
  dampingFactor={0.05}
  minDistance={2}
  maxDistance={20}
  minPolarAngle={0}
  maxPolarAngle={Math.PI / 2}  // prevent going below ground
/>

Other Controls

Component Use Case
CameraControls Full-featured camera (recommended for complex scenes)
MapControls Top-down map navigation (orbit restricted to vertical axis)
PresentationControls Drag-to-rotate with spring physics (product viewers)
ScrollControls Scroll-driven animation (pages prop sets scroll length)
TransformControls Translate/rotate/scale gizmo on selected objects
DragControls Drag objects in 3D space
KeyboardControls Keyboard input as React context
FaceControls Face-tracking camera movement

ScrollControls Pattern

import { ScrollControls, useScroll } from '@react-three/drei'

<ScrollControls pages={3} damping={0.1}>
  <ScrollScene />
</ScrollControls>

function ScrollScene() {
  const scroll = useScroll()
  useFrame(() => {
    const offset = scroll.offset // 0 to 1
  })
  return <mesh />
}

Environment and Staging

Environment

Loads HDR environment maps for realistic reflections and lighting.

import { Environment } from '@react-three/drei'

// Preset (downloads from polyhaven CDN)
<Environment preset="city" background blur={0.5} />

// Custom HDR file
<Environment files="/env.hdr" background />

// Custom environment with Lightformers
<Environment background>
  <Lightformer form="rect" intensity={2} position={[0, 5, -5]} scale={[10, 5, 1]} />
</Environment>

Valid presets: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse.

Stage

Complete lighting and shadow setup in one component. Ideal for product viewers.

import { Stage } from '@react-three/drei'

<Stage preset="rembrandt" intensity={0.5} environment="city" adjustCamera>
  <Model />
</Stage>

Shadow Components

Component Use Case Key Props
ContactShadows Soft ground shadows (no light needed) opacity, scale, blur, far, resolution, color
AccumulativeShadows High-quality baked soft shadows frames, alphaTest, scale, opacity
RandomizedLight Child of AccumulativeShadows amount, radius, intensity, position
BakeShadows Bake shadow maps once, stop updating
SoftShadows PCSS soft shadows for real-time lights

AccumulativeShadows Pattern

<AccumulativeShadows temporal frames={100} scale={10} position={[0, -0.5, 0]}>
  <RandomizedLight amount={8} radius={4} position={[5, 5, -10]} />
</AccumulativeShadows>

Atmosphere

Component Purpose Key Props
Sky Procedural sky dome sunPosition, turbidity, rayleigh
Stars Particle starfield radius, count, factor, fade
Sparkles Floating particles count, size, speed, color
Cloud Volumetric clouds opacity, speed, segments, bounds

Text and HTML

Text (SDF)

High-quality 2D text rendered with signed distance fields via troika-three-text.

import { Text } from '@react-three/drei'

<Text
  fontSize={0.5}
  color="white"
  anchorX="center"
  anchorY="middle"
  maxWidth={2}
  font="/fonts/Inter-Bold.woff"
>
  Hello World
</Text>

Text3D

Extruded 3D geometry text. Requires a JSON font file (use facetype.js to convert).

import { Text3D, Center } from '@react-three/drei'

<Center>
  <Text3D font="/fonts/Inter_Bold.json" size={0.75} height={0.2} bevelEnabled bevelSize={0.02}>
    Hello
    <meshStandardMaterial color="orange" />
  </Text3D>
</Center>

Html

Renders DOM elements positioned in 3D space.

import { Html } from '@react-three/drei'

<mesh position={[0, 2, 0]}>
  <Html
    transform            // transforms with 3D position
    distanceFactor={10}  // scales with distance
    occlude              // hides behind 3D objects
    center               // centers the HTML element
    className="label"
  >
    <div style={{ color: 'white' }}>Annotation</div>
  </Html>
</mesh>

Billboard

ALWAYS faces the camera. Use for labels and sprites.

import { Billboard, Text } from '@react-three/drei'

<Billboard follow={true} lockX={false} lockY={false} lockZ={false}>
  <Text fontSize={0.5}>Always Visible</Text>
</Billboard>

Hud

Renders a heads-up display in a separate orthographic scene.

import { Hud, OrthographicCamera } from '@react-three/drei'

<Hud renderPriority={1}>
  <OrthographicCamera makeDefault position={[0, 0, 5]} />
  <Text position={[0, 0, 0]} fontSize={0.1}>HUD Text</Text>
</Hud>

Materials

Component Purpose
MeshReflectorMaterial Reflective floors with blur, distortion, resolution
MeshTransmissionMaterial Glass with chromatic aberration, distortion, thickness
MeshRefractionMaterial Refraction using environment cube map
MeshWobbleMaterial Animated wobble on MeshStandardMaterial
MeshDistortMaterial Perlin noise distortion on MeshStandardMaterial
MeshDiscardMaterial Renders nothing (shadow-only objects)
shaderMaterial Helper to create custom ShaderMaterial as JSX

MeshReflectorMaterial Example

<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]}>
  <planeGeometry args={[50, 50]} />
  <MeshReflectorMaterial
    blur={[300, 100]}
    resolution={1024}
    mixBlur={1}
    mixStrength={50}
    roughness={1}
    depthScale={1.2}
    minDepthThreshold={0.4}
    maxDepthThreshold={1.4}
    color="#151515"
    metalness={0.5}
  />
</mesh>

shaderMaterial Helper

import { shaderMaterial } from '@react-three/drei'
import { extend } from '@react-three/fiber'

const WaveMaterial = shaderMaterial(
  { uTime: 0, uColor: new THREE.Color(0.2, 0.0, 0.1) },
  /* vertex */ `varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
  /* fragment */ `uniform float uTime; uniform vec3 uColor; varying vec2 vUv; void main() { gl_FragColor = vec4(vUv * uColor, 1.0); }`
)
extend({ WaveMaterial })
// Usage: <waveMaterial uTime={clock.elapsedTime} />

Loaders

ALWAYS wrap loader-consuming components in <Suspense>.

Hook Returns Preload
useGLTF(url) { nodes, materials, scene, animations } useGLTF.preload(url)
useTexture(url) THREE.Texture or map object useTexture.preload(url)
useFBX(url) THREE.Group useFBX.preload(url)
useKTX2(url) Compressed texture useKTX2.preload(url)
useFont(url) Font data for Text3D useFont.preload(url)
useAnimations(clips, ref) { actions, names, mixer, ref }
useVideoTexture(url) THREE.VideoTexture

useGLTF Pattern

import { useGLTF } from '@react-three/drei'

function Model(props) {
  const { nodes, materials } = useGLTF('/model.glb')
  return (
    <group {...props}>
      <mesh geometry={nodes.Body.geometry} material={materials.Metal} />
    </group>
  )
}
useGLTF.preload('/model.glb')

useTexture with Multiple Maps

const textures = useTexture({
  map: '/color.jpg',
  normalMap: '/normal.jpg',
  roughnessMap: '/roughness.jpg',
  aoMap: '/ao.jpg',
})
// Spread directly onto material
<meshStandardMaterial {...textures} />

useAnimations Pattern

function AnimatedModel() {
  const group = useRef()
  const { nodes, animations } = useGLTF('/character.glb')
  const { actions } = useAnimations(animations, group)

  useEffect(() => {
    actions['Walk']?.play()
    return () => actions['Walk']?.stop()
  }, [actions])

  return <group ref={group}><primitive object={nodes.Scene} /></group>
}

Performance

Instances

ALWAYS use for large numbers of identical meshes (>100). Reduces draw calls from N to 1.

import { Instances, Instance } from '@react-three/drei'

<Instances limit={1000} range={1000}>
  <boxGeometry />
  <meshStandardMaterial />
  {positions.map((pos, i) => (
    <Instance key={i} position={pos} color="orange" />
  ))}
</Instances>

Merged

Merges different geometries into a single draw call.

import { Merged } from '@react-three/drei'

function Furniture({ nodes }) {
  return (
    <Merged meshes={[nodes.Chair, nodes.Table, nodes.Lamp]}>
      {(Chair, Table, Lamp) => (
        <>
          <Chair position={[0, 0, 0]} />
          <Table position={[2, 0, 0]} />
          <Lamp position={[1, 1, 0]} />
        </>
      )}
    </Merged>
  )
}

Performance Helpers

Component Purpose
Detailed LOD — switches geometry based on camera distance
BakeShadows Bakes shadows once, stops updating
AdaptiveDpr Lowers device pixel ratio during performance drops
AdaptiveEvents Reduces event frequency during performance drops
PerformanceMonitor Monitors FPS, triggers regression callbacks
Bvh BVH-accelerated raycasting for complex meshes
meshBounds Fast bounding-box raycasting (replaces per-triangle)

PerformanceMonitor Pattern

<PerformanceMonitor
  onIncline={() => setDpr(2)}
  onDecline={() => setDpr(1)}
  flipflops={3}
  onFallback={() => setDpr(0.5)}
/>

Staging and Layout

Component Purpose Key Props
Center Centers children at origin top, right, bottom, left, front, back
Float Floating hover animation speed, rotationIntensity, floatIntensity
Bounds Auto-fit camera to content fit, clip, observe, margin
Resize Normalizes children to unit size width, height, depth

Abstractions and Effects

Component Purpose
Edges Renders wireframe edges
Outlines Screen-space outlines
Trail Motion trail behind objects
Decal Project texture onto mesh surface
Splat Gaussian splatting renderer
Clone Deep clone with shared geometry/materials
Image Texture-mapped plane with shader effects
MeshPortalMaterial Portal — renders scene inside mesh surface
GradientTexture Procedural gradient texture

Gizmos

Component Purpose
GizmoHelper Viewport orientation widget
PivotControls Interactive pivot gizmo (translate/rotate/scale)
TransformControls Three.js TransformControls wrapper
Grid Infinite configurable grid plane
Helper / useHelper Visualize light/camera helpers

Component Selection Guide

Scenario Component
Product viewer Stage + OrbitControls + Environment
Architectural walkthrough CameraControls + Environment + ContactShadows
Scrolling experience ScrollControls + useScroll
Data visualization Instances + Html + Billboard
Text labels in 3D Text (2D) or Text3D (extruded) + Billboard
Glass/transparent objects MeshTransmissionMaterial + Environment
Reflective floors MeshReflectorMaterial
Large identical meshes Instances (>100) or Merged (mixed geometries)
Model loading useGLTF + Suspense + .preload()
HUD / overlay Hud or Html with fullscreen

Reference Links

Official Sources

Related skills
Installs
8
GitHub Stars
1
First Seen
Apr 1, 2026