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.
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)
})
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
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)
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)
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
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
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
Three.js uses a right-handed coordinate system:
// Axes helper
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper) // Red=X, Green=Y, Blue=Z
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
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)
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()
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'
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)
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)
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()
}
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)
}
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)
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)
THREE.LOD for distance-based mesh switchinggetWorldPosition 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)
threejs-geometry - Geometry creation and manipulationthreejs-materials - Material types and propertiesthreejs-lighting - Light types and shadows