Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    zocomputer

    threejs-fundamentals

    zocomputer/threejs-fundamentals
    Coding

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Three.js scene setup, cameras, renderer, Object3D hierarchy, coordinate systems...

    SKILL.md

    Three.js Fundamentals

    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();
    }
    

    Clock for Animation

    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);
    }
    

    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);
    

    See Also

    • threejs-geometry - Geometry creation and manipulation
    • threejs-materials - Material types and properties
    • threejs-lighting - Light types and shadows
    Recommended Servers
    Draw.io
    Draw.io
    Thoughtbox
    Thoughtbox
    Svelte
    Svelte
    Repository
    zocomputer/skills
    Files