๐Ÿ“‹ Instanced Meshes

If you have multiple identical meshes in your scene, use instanced meshes to reduce the number of draw calls. This is especially useful for large scenes with many trees, rocks, or other objects that are repeated many times.

Drei Instances and Merged

If using React Three Fiber with Drei, you can use <Instances />:

import { Instance, Instances } from '@react-three/drei'
 
import { treeGeometry, treeMaterial } from 'lib/resources'
 
const trees = [
  { id: 1, position: [0, 0, 0] },
  { id: 2, position: [1, 0, 0] },
  { id: 3, position: [2, 0, 0] },
]
 
const Trees = () => (
  <Instances geometry={treeGeometry} material={treeMaterial}>
    {tree.map(t => (
      <Instance key={t.id} position={t.position} />
    ))}
  </Instances>
)

If you need multiple instanced meshes per entity, you can use <Merged />:

import { Merged } from '@react-three/drei'
 
import { leavesGeometry, leavesMaterial, trunkGeometry, trunkMaterial } from 'lib/resources'
 
const trees = [
  { id: 1, position: [0, 0, 0] },
  { id: 2, position: [1, 0, 0] },
  { id: 3, position: [2, 0, 0] },
]
 
const Trees = () => (
  <Merged meshes={[leaves, trunk]}>
    {(Leaves, Trunk) => (
      <>
        {tree.map(t => (
          <Fragment key={t.id}>
            <Leaves position={[t.position[0], t.position[1] + 5, t.position[2]]} />
            <Trunk position={t.position} />
          </Fragment>
        ))}
      </>
    )}
  </Merged>
)

This works great for static meshes, but not for animated skinned meshes.

Instanced Skinned Meshes

Instanced skinned meshes (animated characters rendered via instancing) are not straightforward in Three.js. WebGPU has native support, while WebGL requires workarounds. One technique from NVIDIA GPU Gems encodes all frames of all animations into a texture and looks up bone matrices from that texture in the vertex shader.

Resources