Atlaslog
Atlaslog / three.js / Tutorial / Performance and instancing
three.js · Tutorial

Performance and instancing

Quick answer

This tutorial attacks draw-call overhead rather than triangle count. It builds trunk and leaf InstancedMesh objects for thousands of trees, fills matrices with setMatrixAt and colors with setColorAt, and flags instanceMatrix and instanceColor for upload. It then merges static varied shapes with BufferGeometryUtils.mergeGeometries and switches detail levels through LOD.update. Readers can choose instancing, merging, culling or LOD based on renderer.info.render.calls.

Last verified 2026-11-03 · three.js 0.160.0 · Cite this page
Key points
Example
const COUNT = 8000;

const trunk = new THREE.CylinderGeometry(0.6, 0.9, 12, 6);
const leaf = new THREE.SphereGeometry(3.4, 8, 6);

const trunkMesh = new THREE.InstancedMesh(trunk, trunkMaterial, COUNT);
const leafMesh = new THREE.InstancedMesh(leaf, leafMaterial, COUNT);

const dummy = new THREE.Object3D();
const color = new THREE.Color();

for (let i = 0; i < COUNT; i++) {
  const x = (Math.random() - 0.5) * 1600;
  const z = (Math.random() - 0.5) * 1600;
  const s = 0.7 + Math.random() * 0.6;

  dummy.position.set(x, 6 * s, z);
  dummy.rotation.y = Math.random() * Math.PI * 2;
  dummy.scale.set(s, s, s);
  dummy.updateMatrix();
  trunkMesh.setMatrixAt(i, dummy.matrix);

  dummy.position.y = 12 * s + 2.4 * s;
  dummy.scale.setScalar(s);
  dummy.updateMatrix();
  leafMesh.setMatrixAt(i, dummy.matrix);

  color.setHSL(0.28 + Math.random() * 0.08, 0.45, 0.32 + Math.random() * 0.12);
  leafMesh.setColorAt(i, color);
}

trunkMesh.instanceMatrix.needsUpdate = true;
leafMesh.instanceMatrix.needsUpdate = true;
leafMesh.instanceColor.needsUpdate = true;

scene.add(trunkMesh, leafMesh);
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js';

const parts = [];

buildings.forEach(function (b) {
  const geo = new THREE.BoxGeometry(b.w, b.h, b.d);
  geo.translate(b.x, b.h / 2, b.z);
  geo.deleteAttribute('uv');          // 属性不一致会导致合并失败
  parts.push(geo);
});

const merged = mergeGeometries(parts, false);
const mesh = new THREE.Mesh(merged, new THREE.MeshStandardMaterial({
  color: 0x9aa7b4,
  roughness: 0.9
}));

scene.add(mesh);
Notes
Runnable examplesChinese originalAll Tutorials
English edition written for Atlaslog. Code is taken from the original Chinese page and runs unchanged.
Cite this page

Atlaslog (2026). Performance and instancing. https://www.jingweizhi.com/en/three/tutorials/instancing.html (accessed 2026-11-03).