skills/5dlabs/cto/three-js

three-js

SKILL.md

Three.js Best Practices

Comprehensive performance optimization guide for Three.js applications with 100+ rules across 17 categories.

When to Apply

Reference these guidelines when:

  • Setting up a new Three.js project
  • Writing or reviewing Three.js code
  • Optimizing performance or fixing memory leaks
  • Working with custom shaders (GLSL or TSL)
  • Implementing WebGPU features
  • Building VR/AR experiences with WebXR

Rule Categories by Priority

Priority Category Impact Prefix
0 Modern Setup & Imports FUNDAMENTAL setup-
1 Memory Management & Dispose CRITICAL memory-
2 Render Loop Optimization CRITICAL render-
3 Geometry & Buffer Management HIGH geometry-
4 Material & Texture Optimization HIGH material-
5 Lighting & Shadows MEDIUM-HIGH lighting-
6 Scene Graph Organization MEDIUM scene-
7-8 Shader Best Practices MEDIUM shader-, tsl-
9-17 Loading, Camera, Animation, Physics, WebXR, Audio, Mobile, Production, Debug VARIES -

Quick Reference

Modern Import Maps

<script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.182.0/examples/jsm/",
    "three/tsl": "https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.tsl.js"
  }
}
</script>

Memory Management (CRITICAL)

Always dispose resources:

function disposeObject(obj) {
  if (obj.geometry) obj.geometry.dispose();
  if (obj.material) {
    if (Array.isArray(obj.material)) {
      obj.material.forEach(m => m.dispose());
    } else {
      obj.material.dispose();
    }
  }
}

// Recursive disposal for hierarchies
function disposeHierarchy(obj) {
  obj.traverse(child => disposeObject(child));
}

Render Loop (CRITICAL)

// Use setAnimationLoop, not manual RAF
renderer.setAnimationLoop(animate);

// Never allocate in render loop
const _tempVector = new THREE.Vector3();  // Reuse outside loop

function animate(time) {
  // Use cached objects
  _tempVector.set(0, 1, 0);
  
  // Use delta time for animations
  const delta = clock.getDelta();
  mixer.update(delta);
  
  renderer.render(scene, camera);
}

Geometry (HIGH)

// Use InstancedMesh for identical objects
const mesh = new THREE.InstancedMesh(geometry, material, count);
const matrix = new THREE.Matrix4();

for (let i = 0; i < count; i++) {
  matrix.setPosition(positions[i]);
  mesh.setMatrixAt(i, matrix);
}
mesh.instanceMatrix.needsUpdate = true;

Materials & Textures (HIGH)

// Reuse materials
const sharedMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 });

// Use compressed textures
const ktx2Loader = new KTX2Loader()
  .setTranscoderPath('path/to/basis/')
  .detectSupport(renderer);

// Power-of-two texture dimensions
// 512x512, 1024x1024, 2048x2048

Mobile Optimization

const isMobile = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent);

// Limit pixel ratio
renderer.setPixelRatio(Math.min(window.devicePixelRatio, isMobile ? 1.5 : 2));

// Reduce shadow map size on mobile
if (isMobile) {
  light.shadow.mapSize.width = 512;
  light.shadow.mapSize.height = 512;
}

TSL (Three.js Shading Language)

import { texture, uv, color, time, sin } from 'three/tsl';

const material = new THREE.MeshStandardNodeMaterial();
material.colorNode = texture(map).mul(color(0xff0000));
material.colorNode = color(0x00ff00).mul(sin(time).mul(0.5).add(0.5));

Key Patterns

Pattern Benefit
Use InstancedMesh 100x draw calls → 1 draw call
Merge static geometries Reduce draw calls
Use LOD (Level of Detail) Performance at distance
Enable frustum culling Skip off-screen objects
Use texture atlases Reduce material switches
Bake lighting Eliminate runtime shadows

Anti-Patterns

Anti-Pattern Fix
Creating objects in render loop Cache and reuse
Not disposing resources Always call .dispose()
Using BufferGeometry constructor Use specific geometry classes
Too many lights Limit to 3-4 dynamic lights
High pixel ratio on mobile Cap at 1.5-2

Attribution

Based on emalorenzo/three-agent-skills three-best-practices - 53+ installs. Official guidelines from Three.js llms branch maintained by mrdoob.

Weekly Installs
3
Repository
5dlabs/cto
First Seen
Jan 24, 2026
Installed on
claude-code2
windsurf1
trae1
opencode1
codex1
antigravity1