Threejs Fundamentals

calesthio/OpenMontage/.agents/skills/threejs-fundamentals

by calesthio9327439db69021ab4b0e2776729bf3b58fdb5a87No license65K starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated 5 days ago

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.

AI-generated overview

Reference guide for Three.js scene setup, cameras, renderers, Object3D hierarchy and coordinate systems.

What it does
This skill is an instructional reference for Three.js fundamentals. It documents scene, camera and renderer setup, Object3D hierarchy and transforms, the right-handed coordinate system, math utilities such as Vector3, Matrix4, Quaternion, Euler and Color, and common patterns like cleanup, animation clocks, responsive canvases and loading managers. It also lists performance tips and points to related geometry, materials and lighting skills.
When to use it
Use it when setting up a 3D scene, creating cameras, configuring renderers, managing object hierarchies or working with transforms in Three.js. It suits developers who need quick reference code for core Three.js classes and patterns.
Requirements
No scripts are included; it is instructions only. The code examples assume the three package is available in the project, and some examples reference optional addons such as GLTFLoader and BufferGeometryUtils.

Three.js Fundamentals

Quick Start

javascript
import * as THREE from "three";
// Create scene, camera, rendererconst 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 meshconst 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 lightscene.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 loopfunction animate() {  requestAnimationFrame(animate);  cube.rotation.x += 0.01;  cube.rotation.y += 0.01;  renderer.render(scene, camera);}animate();
// Handle resizewindow.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 colorscene.background = texture; // Skybox texturescene.background = cubeTexture; // Cubemapscene.environment = envMap; // Environment map for PBRscene.fog = new THREE.Fog(0xffffff, 1, 100); // Linear fogscene.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 reflectionsmaterial.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 mappingrenderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.toneMappingExposure = 1.0;
// Color space (Three.js r152+)renderer.outputColorSpace = THREE.SRGBColorSpace;
// Shadowsrenderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Clear colorrenderer.setClearColor(0x000000, 1);
// Renderrenderer.render(scene, camera);

Object3D

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

javascript
const obj = new THREE.Object3D();
// Transformobj.position.set(x, y, z);obj.rotation.set(x, y, z); // Euler angles (radians)obj.quaternion.set(x, y, z, w); // Quaternion rotationobj.scale.set(x, y, z);
// Local vs World transformsobj.getWorldPosition(targetVector);obj.getWorldQuaternion(targetQuaternion);obj.getWorldDirection(targetVector);
// Hierarchyobj.add(child);obj.remove(child);obj.parent;obj.children;
// Visibilityobj.visible = false;
// Layers (for selective rendering/raycasting)obj.layers.set(1);obj.layers.enable(2);obj.layers.disable(0);
// Traverse hierarchyobj.traverse((child) => {  if (child.isMesh) child.material.color.set(0xff0000);});
// Matrix updatesobj.matrixAutoUpdate = true; // Default: auto-update matricesobj.updateMatrix(); // Manual matrix updateobj.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 groupgroup.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 propertiesmesh.geometry;mesh.material;mesh.castShadow = true;mesh.receiveShadow = true;
// Frustum cullingmesh.frustumCulled = true; // Default: skip if outside camera view
// Render ordermesh.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 helperconst 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 vv.angleTo(v2);
// Transformv.applyMatrix4(matrix);v.applyQuaternion(q);v.project(camera); // World to NDCv.unproject(camera); // NDC to world

Matrix4

javascript
const m = new THREE.Matrix4();m.identity();m.copy(other);m.clone();
// Build transformsm.makeTranslation(x, y, z);m.makeRotationX(theta);m.makeRotationY(theta);m.makeRotationZ(theta);m.makeRotationFromQuaternion(q);m.makeScale(x, y, z);
// Compose/decomposem.compose(position, quaternion, scale);m.decompose(position, quaternion, scale);
// Operationsm.multiply(m2); // m = m * m2m.premultiply(m2); // m = m2 * mm.invert();m.transpose();
// Camera matricesm.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 interpolationq.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 rangecolor.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();}

Clock for Animation

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

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 geometriesimport { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";const merged = mergeGeometries([geo1, geo2, geo3]);
// LODconst 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

Source and attribution

Source:calesthio/OpenMontagein.agents/skills/threejs-fundamentalsat commit9327439

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal