threejs-animation
Keyframe, skeletal and morph-target animation, procedural motion and clip blending, on WebGL or with WebGPU and TSL. Use when…
Light types and physical units, shadow maps, HDR environment lighting, light probes, and lighting performance, on WebGL or with WebGPU and TSL. Use when adding or tuning lights, fixing shadow acne, setting up image-based lighting, or dimming an environment map.
Claude Code
$ npx -y skills add cloudai-x/threejs-skills --skill threejs-lighting --agent claude-code
Codex
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a codex -y
Cursor
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a cursor -y
Gemini CLI
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a gemini-cli -y
GitHub Copilot
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a github-copilot -y
OpenCode
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a opencode -y
Windsurf
$ npx skills add cloudai-x/threejs-skills --skill threejs-lighting -a windsurf -y
name: threejs-lighting description: "Light types and physical units, shadow maps, HDR environment lighting, light probes, and lighting performance, on WebGL or with WebGPU and TSL. Use when adding or tuning lights, fixing shadow acne, setting up image-based lighting, or dimming an environment map."
Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer.
import * as THREE from "three";
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(4, 3, 8);
// A single directional light: intensity is a plain multiplier, no distance falloff
const dirLight = new THREE.DirectionalLight(0xffffff, 3);
dirLight.position.set(5, 10, 5);
scene.add(dirLight);
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshStandardMaterial({ color: 0x808080 })
);
floor.rotation.x = -Math.PI / 2;
scene.add(floor);
const mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshStandardMaterial({ color: 0x3a76c4 })
);
scene.add(mesh);
// Shadows need three switches: renderer, light, and the meshes that cast and receive
renderer.shadowMap.enabled = true;
dirLight.castShadow = true;
mesh.castShadow = true;
floor.receiveShadow = true;
function animate() {
renderer.render(scene, camera);
}
renderer.setAnimationLoop(animate);| Light | Shadows | Intensity | Notes | |---|---|---|---| | AmbientLight | no | multiplier | Flat fill from every direction | | HemisphereLight | no | multiplier | Sky color from above, ground color from below | | DirectionalLight | yes | multiplier | Parallel rays (sun); shines at its target | | SunLight (addon) | yes, cascaded | multiplier | Shadow frustum fitted to the view automatically | | PointLight | yes, six faces | candela | Inverse-square falloff (decay 2) | | SpotLight | yes | candela | Cone; inverse-square falloff (decay 2) | | RectAreaLight | no | nits | Only MeshStandardMaterial and MeshPhysicalMaterial | | LightProbe | no | multiplier | Spherical-harmonics ambient, usually baked |
PointLight and SpotLight intensity is candela with inverse-square falloff (`decay` 2 by default): a 1-candela light 5 units away contributes 1/25, so useful values depend on distance and typically run to the hundreds (the official docs' examples use 80 to 1000). `light.power` sets the same thing in lumens. `light.distance` is a smooth cutoff range (0 means no limit). Directional, ambient and hemisphere intensities are plain multipliers with no unit. RectAreaLight intensity is nits (candela per square metre).
// AmbientLight(color, intensity) — a flat multiplier on every lit material const ambient = new THREE.AmbientLight(0x404040, 0.5); scene.add(ambient); // HemisphereLight(skyColor, groundColor, intensity) const hemi = new THREE.HemisphereLight(0x87ceeb, 0x8b6f47, 0.6); scene.add(hemi);
// DirectionalLight(color, intensity): parallel rays from position towards target; the distance only matters to the shadow camera const dirLight = new THREE.DirectionalLight(0xffffff, 3); dirLight.position.set(5, 10, 5); // Shines from its position towards target; add the target to the scene when you move it dirLight.target.position.set(0, 0, 0); scene.add(dirLight.target); scene.add(dirLight);
`SunLight` (`three/addons/lights/SunLight.js`) is a parallel light with two cascaded shadow maps, suited to large scenes. It has no target: it shines from its position towards the origin, straight down by default. With WebGLRenderer it works out of the box; under WebGPURenderer register it first (see WebGPU and TSL).
import { SunLight } from "three/addons/lights/SunLight.js";
const sun = new SunLight(0xfff2e3, 3);
sun.position.set(100, 160, 60);
sun.castShadow = true;
scene.add(sun);The cascades are fitted automatically to slices of the camera's view frustum, up to `sun.shadow.camera.far` or the view camera's far plane, whichever is smaller. `shadow.camera.left/right/top/bottom` are ignored; the default `mapSize` is 1024 × 1024 per cascade. There is no shadow frustum to hand-tighten.
// PointLight(color, intensity in candela, distance, decay) const bulb = new THREE.PointLight(0xffdcb0, 100, 20, 2); bulb.position.set(0, 4, 0); scene.add(bulb); // SpotLight(color, intensity in candela, distance, angle, penumbra, decay) const deskLamp = new THREE.SpotLight(0xffffff, 250, 30, Math.PI / 6, 0.4, 2); deskLamp.position.set(2, 5, 0); deskLamp.target.position.set(0, 0, 0); scene.add(deskLamp.target); scene.add(deskLamp); // Prefer lumens: power writes the candela intensity for you bulb.power = 800;
`angle` is the cone half-angle in radians with an upper bound of Math.PI / 2; `penumbra` (0 to 1) softens the cone edge.
A rectangular emitter for soft window- or strip-style lighting. It lights only MeshStandardMaterial and MeshPhysicalMaterial, and it cannot cast shadows.
import { RectAreaLightHelper } from "three/addons/helpers/RectAreaLightHelper.js";
import { RectAreaLightUniformsLib } from "three/addons/lights/RectAreaLightUniformsLib.js";
// WebGLRenderer: add the LTC lookup textures to the renderer's uniforms, once
RectAreaLightUniformsLib.init();
// RectAreaLight(color, intensity in nits, width, height)
const windowLight = new THREE.RectAreaLight(0xffffff, 5, 4, 10);
windowLight.position.set(-5, 5, 0);
windowLight.lookAt(0, 0, 0); // emits from its front face
scene.add(windowLight);
// The helper must be added as aSkill files that give Claude Code current, verified knowledge of three.js, so the code it writes runs on the release you actually install. The skills target three.js r186 (three@0.186), React Three Fiber 9.8 with drei 10.7, and gltf-transform 4.5.
Keyframe, skeletal and morph-target animation, procedural motion and clip blending, on WebGL or with WebGPU and TSL. Use when…
Shrinking glTF assets for three.js with gltf-transform: inspect, validate and optimize commands, Draco, meshopt and quantization,…
Three.js scene setup: scenes and fog, cameras, the renderer and tone mapping, the animation loop, object hierarchies, transforms,…
Creating and shaping three.js geometry: built-in shapes, 3D text, vertex buffers and attributes, merging, instancing, batching,…
Picking with raycasting, camera controls, transform gizmos, drag, hover and box selection for three.js, identical under WebGL and…
Loading three.js assets: glTF with Draco, meshopt and KTX2 compression, other model formats, textures, HDR and EXR environments,…
Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert…
tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One…