ChatGPT Claude Codex CLI Cohere Cursor DeepSeek Gemini GitHub Copilot GLM Grok Kimi Llama MiniMax Mistral OpenAI opencode Skill

threejs-fundamentals

Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.

LLM Mart · 0 points · 20 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download sickn33-agentic-awesome-skills-skills_threejs-fundamentals-286166a.zip · 4 KB
Part of sickn33/agentic-awesome-skills — 427 skills
This skill couldn't be refreshed from GitHub on the last check — you're seeing the last imported snapshot.

Install

skills CLI npx skills add https://github.com/sickn33/agentic-awesome-skills/tree/main/skills/threejs-fundamentals
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install sickn33-agentic-awesome-skills@llmmart
Git git clone https://github.com/sickn33/agentic-awesome-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole sickn33/agentic-awesome-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Three.js Fundamentals

When to Use

  • You need to set up the core structure of a Three.js scene.
  • The task involves scenes, cameras, renderers, transforms, resize handling, or object hierarchy basics.
  • You want foundational Three.js guidance before working on specialized topics like shaders or post-processing.

Quick Start

import * as THREE from "three";

// Create scene, camera, renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000,
);
const renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);

// Add a mesh
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Add light
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 5, 5);
scene.add(dirLight);

camera.position.z = 5;

// Animation loop
function animate() {
  requestAnimationFrame(animate);
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;
  renderer.render(scene, camera);
}
animate();

// Handle resize
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

Core Classes

Scene

Container for all 3D objects, lights, and cameras.

const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // Solid color
scene.background = texture; // Skybox texture
scene.background = cubeTexture; // Cubemap
scene.environment = envMap; // Environment map for PBR
scene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fog
scene.fog = new THREE.FogExp2(0xffffff, 0.02); // Exponential fog

Cameras

PerspectiveCamera - Most common, simulates human eye.

// PerspectiveCamera(fov, aspect, near, far)
const camera = new THREE.PerspectiveCamera(
  75, // Field of view (degrees)
  window.innerWidth / window.innerHeight, // Aspect ratio
  0.1, // Near clipping plane
  1000, // Far clipping plane
);

camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);
camera.updateProjectionMatrix(); // Call after changing fov, aspect, near, far

OrthographicCamera - No perspective distortion, good for 2D/isometric.

// OrthographicCamera(left, right, top, bottom, near, far)
const aspect = window.innerWidth / window.innerHeight;
const frustumSize = 10;
const camera = new THREE.OrthographicCamera(
  (frustumSize * aspect) / -2,
  (frustumSize * aspect) / 2,
  frustumSize / 2,
  frustumSize / -2,
  0.1,
  1000,
);

ArrayCamera - Multiple viewports with sub-cameras.

const cameras = [];
for (let i = 0; i < 4; i++) {
  const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
  subcamera.viewport = new THREE.Vector4(
    Math.floor(i % 2) * 0.5,
    Math.floor(i / 2) * 0.5,
    0.5,
    0.5,
  );
  cameras.push(subcamera);
}
const arrayCamera = new THREE.ArrayCamera(cameras);

CubeCamera - Renders environment maps for reflections.

const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
scene.add(cubeCamera);

// Use for reflections
material.envMap = cubeRenderTarget.texture;

// Update each frame (expensive!)
cubeCamera.position.copy(reflectiveMesh.position);
cubeCamera.update(renderer, scene);

WebGLRenderer

const renderer = new THREE.WebGLRenderer({
  canvas: document.querySelector("#canvas"), // Optional existing canvas
  antialias: true, // Smooth edges
  alpha: true, // Transparent background
  powerPreference: "high-performance", // GPU hint
  preserveDrawingBuffer: true, // For screenshots
});

renderer.setSize(width, height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

// Tone mapping
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;

// Color space (Three.js r152+)
renderer.outputColorSpace = THREE.SRGBColorSpace;

// Shadows
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

// Clear color
renderer.setClearColor(0x000000, 1);

// Render
renderer.render(scene, camera);

Object3D

Base class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.

const obj = new THREE.Object3D();

// Transform
obj.position.set(x, y, z);
obj.rotation.set(x, y, z); // Euler angles (radians)
obj.quaternion.set(x, y, z, w); // Quaternion rotation
obj.scale.set(x, y, z);

// Local vs World transforms
obj.getWorldPosition(targetVector);
obj.getWorldQuaternion(targetQuaternion);
obj.getWorldDirection(targetVector);

// Hierarchy
obj.add(child);
obj.remove(child);
obj.parent;
obj.children;

// Visibility
obj.visible = false;

// Layers (for selective rendering/raycasting)
obj.layers.set(1);
obj.layers.enable(2);
obj.layers.disable(0);

// Traverse hierarchy
obj.traverse((child) => {
  if (child.isMesh) child.material.color.set(0xff0000);
});

// Matrix updates
obj.matrixAutoUpdate = true; // Default: auto-update matrices
obj.updateMatrix(); // Manual matrix update
obj.updateMatrixWorld(true); // Update world matrix recursively

Group

Empty container for organizing objects.

const group = new THREE.Group();
group.add(mesh1);
group.add(mesh2);
scene.add(group);

// Transform entire group
group.position.x = 5;
group.rotation.y = Math.PI / 4;

Mesh

Combines geometry and material.

const mesh = new THREE.Mesh(geometry, material);

// Multiple materials (one per geometry group)
const mesh = new THREE.Mesh(geometry, [material1, material2]);

// Useful properties
mesh.geometry;
mesh.material;
mesh.castShadow = true;
mesh.receiveShadow = true;

// Frustum culling
mesh.frustumCulled = true; // Default: skip if outside camera view

// Render order
mesh.renderOrder = 10; // Higher = rendered later

Coordinate System

Three.js uses a right-handed coordinate system:

  • +X points right
  • +Y points up
  • +Z points toward viewer (out of screen)
// Axes helper
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper); // Red=X, Green=Y, Blue=Z

Math Utilities

Vector3

const v = new THREE.Vector3(x, y, z);
v.set(x, y, z);
v.copy(otherVector);
v.clone();

// Operations (modify in place)
v.add(v2);
v.sub(v2);
v.multiply(v2);
v.multiplyScalar(2);
v.divideScalar(2);
v.normalize();
v.negate();
v.clamp(min, max);
v.lerp(target, alpha);

// Calculations (return new value)
v.length();
v.lengthSq(); // Faster than length()
v.distanceTo(v2);
v.dot(v2);
v.cross(v2); // Modifies v
v.angleTo(v2);

// Transform
v.applyMatrix4(matrix);
v.applyQuaternion(q);
v.project(camera); // World to NDC
v.unproject(camera); // NDC to world

Matrix4

const m = new THREE.Matrix4();
m.identity();
m.copy(other);
m.clone();

// Build transforms
m.makeTranslation(x, y, z);
m.makeRotationX(theta);
m.makeRotationY(theta);
m.makeRotationZ(theta);
m.makeRotationFromQuaternion(q);
m.makeScale(x, y, z);

// Compose/decompose
m.compose(position, quaternion, scale);
m.decompose(position, quaternion, scale);

// Operations
m.multiply(m2); // m = m * m2
m.premultiply(m2); // m = m2 * m
m.invert();
m.transpose();

// Camera matrices
m.makePerspective(left, right, top, bottom, near, far);
m.makeOrthographic(left, right, top, bottom, near, far);
m.lookAt(eye, target, up);

Quaternion

const q = new THREE.Quaternion();
q.setFromEuler(euler);
q.setFromAxisAngle(axis, angle);
q.setFromRotationMatrix(matrix);

q.multiply(q2);
q.slerp(target, t); // Spherical interpolation
q.normalize();
q.invert();

Euler

const euler = new THREE.Euler(x, y, z, "XYZ"); // Order matters!
euler.setFromQuaternion(q);
euler.setFromRotationMatrix(m);

// Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'

Color

const color = new THREE.Color(0xff0000);
const color = new THREE.Color("red");
const color = new THREE.Color("rgb(255, 0, 0)");
const color = new THREE.Color("#ff0000");

color.setHex(0x00ff00);
color.setRGB(r, g, b); // 0-1 range
color.setHSL(h, s, l); // 0-1 range

color.lerp(otherColor, alpha);
color.multiply(otherColor);
color.multiplyScalar(2);

MathUtils

THREE.MathUtils.clamp(value, min, max);
THREE.MathUtils.lerp(start, end, alpha);
THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
THREE.MathUtils.degToRad(degrees);
THREE.MathUtils.radToDeg(radians);
THREE.MathUtils.randFloat(min, max);
THREE.MathUtils.randInt(min, max);
THREE.MathUtils.smoothstep(x, min, max);
THREE.MathUtils.smootherstep(x, min, max);

Common Patterns

Proper Cleanup

function dispose() {
  // Dispose geometries
  mesh.geometry.dispose();

  // Dispose materials
  if (Array.isArray(mesh.material)) {
    mesh.material.forEach((m) => m.dispose());
  } else {
    mesh.material.dispose();
  }

  // Dispose textures
  texture.dispose();

  // Remove from scene
  scene.remove(mesh);

  // Dispose renderer
  renderer.dispose();
}

Timer and Clock for Animation

Timer (recommended in r183) - pauses when tab is hidden, cleaner API:

const timer = new THREE.Timer();

renderer.setAnimationLoop(() => {
  timer.update();
  const delta = timer.getDelta();
  const elapsed = timer.getElapsed();

  mesh.rotation.y += delta * 0.5;
  renderer.render(scene, camera);
});

Clock (legacy, still works):

const clock = new THREE.Clock();

function animate() {
  const delta = clock.getDelta(); // Time since last frame (seconds)
  const elapsed = clock.getElapsedTime(); // Total time (seconds)

  mesh.rotation.y += delta * 0.5; // Consistent speed regardless of framerate

  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

Animation Loop

Prefer renderer.setAnimationLoop() over manual requestAnimationFrame. It handles WebXR compatibility and is the standard Three.js pattern:

renderer.setAnimationLoop(() => {
  controls.update();
  renderer.render(scene, camera);
});

Responsive Canvas

function onWindowResize() {
  const width = window.innerWidth;
  const height = window.innerHeight;

  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.setSize(width, height);
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
window.addEventListener("resize", onWindowResize);

Loading Manager

const manager = new THREE.LoadingManager();

manager.onStart = (url, loaded, total) => console.log("Started loading");
manager.onLoad = () => console.log("All loaded");
manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
manager.onError = (url) => console.error(`Error loading ${url}`);

const textureLoader = new THREE.TextureLoader(manager);
const gltfLoader = new GLTFLoader(manager);

Performance Tips

  1. Limit draw calls: Merge geometries, use instancing, atlas textures
  2. Frustum culling: Enabled by default, ensure bounding boxes are correct
  3. LOD (Level of Detail): Use THREE.LOD for distance-based mesh switching
  4. Object pooling: Reuse objects instead of creating/destroying
  5. Avoid getWorldPosition in loops: Cache results
// Merge static geometries
import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
const merged = mergeGeometries([geo1, geo2, geo3]);

// LOD
const lod = new THREE.LOD();
lod.addLevel(highDetailMesh, 0);
lod.addLevel(medDetailMesh, 50);
lod.addLevel(lowDetailMesh, 100);
scene.add(lod);

WebGPU Renderer (r183)

Three.js includes an experimental WebGPU renderer as an alternative to WebGL:

import { WebGPURenderer } from "three/addons/renderers/webgpu/WebGPURenderer.js";

const renderer = new WebGPURenderer({ antialias: true });
await renderer.init();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

WebGPU uses TSL (Three.js Shading Language) instead of GLSL. The WebGL renderer remains the default and is fully supported.

See Also

  • threejs-geometry - Geometry creation and manipulation
  • threejs-materials - Material types and properties
  • threejs-lighting - Light types and shadows

Limitations

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Files (agentic-awesome-skills)
  • SKILL.md 13 KB
    ---
    name: threejs-fundamentals
    description: Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems. Use when setting up 3D scenes, creating cameras, configuring renderers, managing object hierarchies, or working with transforms.
    risk: critical
    source: community
    ---
    
    # Three.js Fundamentals
    
    ## When to Use
    - You need to set up the core structure of a Three.js scene.
    - The task involves scenes, cameras, renderers, transforms, resize handling, or object hierarchy basics.
    - You want foundational Three.js guidance before working on specialized topics like shaders or post-processing.
    
    ## Quick Start
    
    ```javascript
    import * as THREE from "three";
    
    // Create scene, camera, renderer
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000,
    );
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    document.body.appendChild(renderer.domElement);
    
    // Add a mesh
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    
    // Add light
    scene.add(new THREE.AmbientLight(0xffffff, 0.5));
    const dirLight = new THREE.DirectionalLight(0xffffff, 1);
    dirLight.position.set(5, 5, 5);
    scene.add(dirLight);
    
    camera.position.z = 5;
    
    // Animation loop
    function animate() {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    }
    animate();
    
    // Handle resize
    window.addEventListener("resize", () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
    ```
    
    ## Core Classes
    
    ### Scene
    
    Container for all 3D objects, lights, and cameras.
    
    ```javascript
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000); // Solid color
    scene.background = texture; // Skybox texture
    scene.background = cubeTexture; // Cubemap
    scene.environment = envMap; // Environment map for PBR
    scene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fog
    scene.fog = new THREE.FogExp2(0xffffff, 0.02); // Exponential fog
    ```
    
    ### Cameras
    
    **PerspectiveCamera** - Most common, simulates human eye.
    
    ```javascript
    // PerspectiveCamera(fov, aspect, near, far)
    const camera = new THREE.PerspectiveCamera(
      75, // Field of view (degrees)
      window.innerWidth / window.innerHeight, // Aspect ratio
      0.1, // Near clipping plane
      1000, // Far clipping plane
    );
    
    camera.position.set(0, 5, 10);
    camera.lookAt(0, 0, 0);
    camera.updateProjectionMatrix(); // Call after changing fov, aspect, near, far
    ```
    
    **OrthographicCamera** - No perspective distortion, good for 2D/isometric.
    
    ```javascript
    // OrthographicCamera(left, right, top, bottom, near, far)
    const aspect = window.innerWidth / window.innerHeight;
    const frustumSize = 10;
    const camera = new THREE.OrthographicCamera(
      (frustumSize * aspect) / -2,
      (frustumSize * aspect) / 2,
      frustumSize / 2,
      frustumSize / -2,
      0.1,
      1000,
    );
    ```
    
    **ArrayCamera** - Multiple viewports with sub-cameras.
    
    ```javascript
    const cameras = [];
    for (let i = 0; i < 4; i++) {
      const subcamera = new THREE.PerspectiveCamera(40, 1, 0.1, 100);
      subcamera.viewport = new THREE.Vector4(
        Math.floor(i % 2) * 0.5,
        Math.floor(i / 2) * 0.5,
        0.5,
        0.5,
      );
      cameras.push(subcamera);
    }
    const arrayCamera = new THREE.ArrayCamera(cameras);
    ```
    
    **CubeCamera** - Renders environment maps for reflections.
    
    ```javascript
    const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256);
    const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);
    scene.add(cubeCamera);
    
    // Use for reflections
    material.envMap = cubeRenderTarget.texture;
    
    // Update each frame (expensive!)
    cubeCamera.position.copy(reflectiveMesh.position);
    cubeCamera.update(renderer, scene);
    ```
    
    ### WebGLRenderer
    
    ```javascript
    const renderer = new THREE.WebGLRenderer({
      canvas: document.querySelector("#canvas"), // Optional existing canvas
      antialias: true, // Smooth edges
      alpha: true, // Transparent background
      powerPreference: "high-performance", // GPU hint
      preserveDrawingBuffer: true, // For screenshots
    });
    
    renderer.setSize(width, height);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    
    // Tone mapping
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.0;
    
    // Color space (Three.js r152+)
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    
    // Shadows
    renderer.shadowMap.enabled = true;
    renderer.shadowMap.type = THREE.PCFSoftShadowMap;
    
    // Clear color
    renderer.setClearColor(0x000000, 1);
    
    // Render
    renderer.render(scene, camera);
    ```
    
    ### Object3D
    
    Base class for all 3D objects. Mesh, Group, Light, Camera all extend Object3D.
    
    ```javascript
    const obj = new THREE.Object3D();
    
    // Transform
    obj.position.set(x, y, z);
    obj.rotation.set(x, y, z); // Euler angles (radians)
    obj.quaternion.set(x, y, z, w); // Quaternion rotation
    obj.scale.set(x, y, z);
    
    // Local vs World transforms
    obj.getWorldPosition(targetVector);
    obj.getWorldQuaternion(targetQuaternion);
    obj.getWorldDirection(targetVector);
    
    // Hierarchy
    obj.add(child);
    obj.remove(child);
    obj.parent;
    obj.children;
    
    // Visibility
    obj.visible = false;
    
    // Layers (for selective rendering/raycasting)
    obj.layers.set(1);
    obj.layers.enable(2);
    obj.layers.disable(0);
    
    // Traverse hierarchy
    obj.traverse((child) => {
      if (child.isMesh) child.material.color.set(0xff0000);
    });
    
    // Matrix updates
    obj.matrixAutoUpdate = true; // Default: auto-update matrices
    obj.updateMatrix(); // Manual matrix update
    obj.updateMatrixWorld(true); // Update world matrix recursively
    ```
    
    ### Group
    
    Empty container for organizing objects.
    
    ```javascript
    const group = new THREE.Group();
    group.add(mesh1);
    group.add(mesh2);
    scene.add(group);
    
    // Transform entire group
    group.position.x = 5;
    group.rotation.y = Math.PI / 4;
    ```
    
    ### Mesh
    
    Combines geometry and material.
    
    ```javascript
    const mesh = new THREE.Mesh(geometry, material);
    
    // Multiple materials (one per geometry group)
    const mesh = new THREE.Mesh(geometry, [material1, material2]);
    
    // Useful properties
    mesh.geometry;
    mesh.material;
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    
    // Frustum culling
    mesh.frustumCulled = true; // Default: skip if outside camera view
    
    // Render order
    mesh.renderOrder = 10; // Higher = rendered later
    ```
    
    ## Coordinate System
    
    Three.js uses a **right-handed coordinate system**:
    
    - **+X** points right
    - **+Y** points up
    - **+Z** points toward viewer (out of screen)
    
    ```javascript
    // Axes helper
    const axesHelper = new THREE.AxesHelper(5);
    scene.add(axesHelper); // Red=X, Green=Y, Blue=Z
    ```
    
    ## Math Utilities
    
    ### Vector3
    
    ```javascript
    const v = new THREE.Vector3(x, y, z);
    v.set(x, y, z);
    v.copy(otherVector);
    v.clone();
    
    // Operations (modify in place)
    v.add(v2);
    v.sub(v2);
    v.multiply(v2);
    v.multiplyScalar(2);
    v.divideScalar(2);
    v.normalize();
    v.negate();
    v.clamp(min, max);
    v.lerp(target, alpha);
    
    // Calculations (return new value)
    v.length();
    v.lengthSq(); // Faster than length()
    v.distanceTo(v2);
    v.dot(v2);
    v.cross(v2); // Modifies v
    v.angleTo(v2);
    
    // Transform
    v.applyMatrix4(matrix);
    v.applyQuaternion(q);
    v.project(camera); // World to NDC
    v.unproject(camera); // NDC to world
    ```
    
    ### Matrix4
    
    ```javascript
    const m = new THREE.Matrix4();
    m.identity();
    m.copy(other);
    m.clone();
    
    // Build transforms
    m.makeTranslation(x, y, z);
    m.makeRotationX(theta);
    m.makeRotationY(theta);
    m.makeRotationZ(theta);
    m.makeRotationFromQuaternion(q);
    m.makeScale(x, y, z);
    
    // Compose/decompose
    m.compose(position, quaternion, scale);
    m.decompose(position, quaternion, scale);
    
    // Operations
    m.multiply(m2); // m = m * m2
    m.premultiply(m2); // m = m2 * m
    m.invert();
    m.transpose();
    
    // Camera matrices
    m.makePerspective(left, right, top, bottom, near, far);
    m.makeOrthographic(left, right, top, bottom, near, far);
    m.lookAt(eye, target, up);
    ```
    
    ### Quaternion
    
    ```javascript
    const q = new THREE.Quaternion();
    q.setFromEuler(euler);
    q.setFromAxisAngle(axis, angle);
    q.setFromRotationMatrix(matrix);
    
    q.multiply(q2);
    q.slerp(target, t); // Spherical interpolation
    q.normalize();
    q.invert();
    ```
    
    ### Euler
    
    ```javascript
    const euler = new THREE.Euler(x, y, z, "XYZ"); // Order matters!
    euler.setFromQuaternion(q);
    euler.setFromRotationMatrix(m);
    
    // Rotation orders: 'XYZ', 'YXZ', 'ZXY', 'XZY', 'YZX', 'ZYX'
    ```
    
    ### Color
    
    ```javascript
    const color = new THREE.Color(0xff0000);
    const color = new THREE.Color("red");
    const color = new THREE.Color("rgb(255, 0, 0)");
    const color = new THREE.Color("#ff0000");
    
    color.setHex(0x00ff00);
    color.setRGB(r, g, b); // 0-1 range
    color.setHSL(h, s, l); // 0-1 range
    
    color.lerp(otherColor, alpha);
    color.multiply(otherColor);
    color.multiplyScalar(2);
    ```
    
    ### MathUtils
    
    ```javascript
    THREE.MathUtils.clamp(value, min, max);
    THREE.MathUtils.lerp(start, end, alpha);
    THREE.MathUtils.mapLinear(value, inMin, inMax, outMin, outMax);
    THREE.MathUtils.degToRad(degrees);
    THREE.MathUtils.radToDeg(radians);
    THREE.MathUtils.randFloat(min, max);
    THREE.MathUtils.randInt(min, max);
    THREE.MathUtils.smoothstep(x, min, max);
    THREE.MathUtils.smootherstep(x, min, max);
    ```
    
    ## Common Patterns
    
    ### Proper Cleanup
    
    ```javascript
    function dispose() {
      // Dispose geometries
      mesh.geometry.dispose();
    
      // Dispose materials
      if (Array.isArray(mesh.material)) {
        mesh.material.forEach((m) => m.dispose());
      } else {
        mesh.material.dispose();
      }
    
      // Dispose textures
      texture.dispose();
    
      // Remove from scene
      scene.remove(mesh);
    
      // Dispose renderer
      renderer.dispose();
    }
    ```
    
    ### Timer and Clock for Animation
    
    **Timer (recommended in r183)** - pauses when tab is hidden, cleaner API:
    
    ```javascript
    const timer = new THREE.Timer();
    
    renderer.setAnimationLoop(() => {
      timer.update();
      const delta = timer.getDelta();
      const elapsed = timer.getElapsed();
    
      mesh.rotation.y += delta * 0.5;
      renderer.render(scene, camera);
    });
    ```
    
    **Clock (legacy, still works):**
    
    ```javascript
    const clock = new THREE.Clock();
    
    function animate() {
      const delta = clock.getDelta(); // Time since last frame (seconds)
      const elapsed = clock.getElapsedTime(); // Total time (seconds)
    
      mesh.rotation.y += delta * 0.5; // Consistent speed regardless of framerate
    
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
    }
    ```
    
    ### Animation Loop
    
    Prefer `renderer.setAnimationLoop()` over manual `requestAnimationFrame`. It handles WebXR compatibility and is the standard Three.js pattern:
    
    ```javascript
    renderer.setAnimationLoop(() => {
      controls.update();
      renderer.render(scene, camera);
    });
    ```
    
    ### Responsive Canvas
    
    ```javascript
    function onWindowResize() {
      const width = window.innerWidth;
      const height = window.innerHeight;
    
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    
      renderer.setSize(width, height);
      renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    }
    window.addEventListener("resize", onWindowResize);
    ```
    
    ### Loading Manager
    
    ```javascript
    const manager = new THREE.LoadingManager();
    
    manager.onStart = (url, loaded, total) => console.log("Started loading");
    manager.onLoad = () => console.log("All loaded");
    manager.onProgress = (url, loaded, total) => console.log(`${loaded}/${total}`);
    manager.onError = (url) => console.error(`Error loading ${url}`);
    
    const textureLoader = new THREE.TextureLoader(manager);
    const gltfLoader = new GLTFLoader(manager);
    ```
    
    ## Performance Tips
    
    1. **Limit draw calls**: Merge geometries, use instancing, atlas textures
    2. **Frustum culling**: Enabled by default, ensure bounding boxes are correct
    3. **LOD (Level of Detail)**: Use `THREE.LOD` for distance-based mesh switching
    4. **Object pooling**: Reuse objects instead of creating/destroying
    5. **Avoid `getWorldPosition` in loops**: Cache results
    
    ```javascript
    // Merge static geometries
    import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
    const merged = mergeGeometries([geo1, geo2, geo3]);
    
    // LOD
    const lod = new THREE.LOD();
    lod.addLevel(highDetailMesh, 0);
    lod.addLevel(medDetailMesh, 50);
    lod.addLevel(lowDetailMesh, 100);
    scene.add(lod);
    ```
    
    ## WebGPU Renderer (r183)
    
    Three.js includes an experimental WebGPU renderer as an alternative to WebGL:
    
    ```javascript
    import { WebGPURenderer } from "three/addons/renderers/webgpu/WebGPURenderer.js";
    
    const renderer = new WebGPURenderer({ antialias: true });
    await renderer.init();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    ```
    
    WebGPU uses TSL (Three.js Shading Language) instead of GLSL. The WebGL renderer remains the default and is fully supported.
    
    ## See Also
    
    - `threejs-geometry` - Geometry creation and manipulation
    - `threejs-materials` - Material types and properties
    - `threejs-lighting` - Light types and shadows
    
    ## Limitations
    - Use this skill only when the task clearly matches the scope described above.
    - Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
    - Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related