Skip to content
Agents tracked: 440 Downloads (7d): 202M down 19.5% GitHub stars: 10.4M Releases (7d): 607 Agent status: 1 with issuesSince last limit reset: Claude 28d · Codex 0d Updated Oct 21, 2026

InstancedMesh in React Three Fiber

Every mesh in a scene costs one draw call. When you need many copies of the same shape, an instancedMesh draws all of them at once and you position each copy yourself.

All React Three Fiber examples React Three Fiber: usage and stats

InstancedMesh in React Three Fiber: screenshot of the example below running
The code below, running in Chromium on our server (Oct 12, 2026). Press Run to see it live and change it.

How it works

  1. Why instancing. The React Three Fiber performance guide treats 1,000 draw calls as the hard maximum and a few hundred as the target, and points to instancing for repeated objects. Here 2,500 cubes are a single draw call. [1]
  2. Create the instanced mesh. <instancedMesh args={[undefined, undefined, COUNT]}> passes the constructor arguments (geometry, material, count). Leaving the first two undefined lets the child geometry and material attach as usual. [2]
  3. Move every instance in useFrame. A reusable Object3D ("dummy") gets a position and scale, updateMatrix() builds its matrix, and setMatrixAt(i, dummy.matrix) copies it into instance i. setColorAt does the same for colours. [2]
  4. Flag the buffers. After the loop, instanceMatrix.needsUpdate = true (and instanceColor.needsUpdate) tells three.js to upload the new values to the GPU on this frame. [2]

Run and edit it

It runs in your browser, in a sandboxed frame that cannot see this site; the packages load from esm.sh only after you press Run.

import { Canvas, useFrame } from '@react-three/fiber'
import { useMemo, useRef } from 'react'
import * as THREE from 'three'

const SIDE = 50
const COUNT = SIDE * SIDE

function Wave() {
  const ref = useRef()
  // reused every frame: no new objects inside the loop
  const dummy = useMemo(() => new THREE.Object3D(), [])
  const color = useMemo(() => new THREE.Color(), [])
  useFrame(({ clock }) => {
    const t = clock.elapsedTime
    let i = 0
    for (let x = 0; x < SIDE; x++) {
      for (let z = 0; z < SIDE; z++) {
        const d = Math.hypot(x - SIDE / 2, z - SIDE / 2)
        const y = Math.sin(d * 0.35 - t * 2) * 0.8
        dummy.position.set(x - SIDE / 2, y, z - SIDE / 2)
        dummy.scale.setScalar(0.8)
        dummy.updateMatrix()
        ref.current.setMatrixAt(i, dummy.matrix)
        ref.current.setColorAt(i, color.setHSL(0.58 + y * 0.08, 0.7, 0.55))
        i++
      }
    }
    ref.current.instanceMatrix.needsUpdate = true
    ref.current.instanceColor.needsUpdate = true
  })
  return (
    <instancedMesh ref={ref} args={[undefined, undefined, COUNT]}>
      <boxGeometry args={[0.9, 0.9, 0.9]} />
      <meshStandardMaterial />
    </instancedMesh>
  )
}

export default function App() {
  return (
    <Canvas camera={{ position: [42, 36, 42], fov: 40 }}>
      <color attach="background" args={['#111']} />
      <ambientLight intensity={0.6} />
      <directionalLight position={[10, 20, 5]} intensity={2.5} />
      <Wave />
    </Canvas>
  )
}
Ctrl/⌘ + Enter runs

Free for signed-in members, with a daily limit. Describe the change in plain words; the new code runs only in your browser.

2,500 cubes drawn in one draw call: one instancedMesh, animated in useFrame by changing each instance's matrix. Code written by AgentGid [1].

Checked Oct 12, 2026: it starts without errors in Chromium with React Three Fiber 9.8.1, three.js 0.186.1, Drei 10.7.9, React 19.3.0. Needs WebGL.

More React Three Fiber examples

Shadows in React Three Fiber useFrame in React Three Fiber onClick and pointer events in React Three Fiber OrbitControls in React Three Fiber

Sources

  1. Docs: Scaling performance
  2. three.js docs: InstancedMesh
  3. Docs: Hooks (useFrame, useThree)

Explanations written by AgentGid from the official docs; the numbers in brackets point here. The code marked "written by AgentGid" is ours and free to copy.

Building something with React Three Fiber? Ask AgentGid →