threejs-animation
Keyframe, skeletal and morph-target animation, procedural motion and clip blending, on WebGL or with WebGPU and TSL. Use when…
Loading three.js assets: glTF with Draco, meshopt and KTX2 compression, other model formats, textures, HDR and EXR environments, progress, caching, cloning and disposal. Use when loading 3D models, textures or environment maps, or managing loading progress, on WebGL or with
Claude Code
$ npx -y skills add cloudai-x/threejs-skills --skill threejs-loaders --agent claude-code
Codex
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a codex -y
Cursor
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a cursor -y
Gemini CLI
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a gemini-cli -y
GitHub Copilot
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a github-copilot -y
OpenCode
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a opencode -y
Windsurf
$ npx skills add cloudai-x/threejs-skills --skill threejs-loaders -a windsurf -y
name: threejs-loaders description: "Loading three.js assets: glTF with Draco, meshopt and KTX2 compression, other model formats, textures, HDR and EXR environments, progress, caching, cloning and disposal. Use when loading 3D models, textures or environment maps, or managing loading progress, on WebGL or with WebGPU and TSL."
Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer.
import * as THREE from "three";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { RoomEnvironment } from "three/addons/environments/RoomEnvironment.js";
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();
scene.environment = new THREE.PMREMGenerator(renderer).fromScene(new RoomEnvironment(), 0.04).texture; // glTF PBR materials render black without lights or an environment
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(2, 1.5, 3);
camera.lookAt(0, 0, 0);
const gltf = await new GLTFLoader().loadAsync("model.glb");
scene.add(gltf.scene);
function animate() {
renderer.render(scene, camera);
}
renderer.setAnimationLoop(animate);One manager coordinates several loaders and reports combined progress. `loadAsync` still rejects on failure; `manager.onError` fires as well.
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
const manager = new THREE.LoadingManager();
manager.onStart = (url, loaded, total) => {
console.log(`Started loading: ${url}`);
};
manager.onProgress = (url, loaded, total) => {
console.log(`Loading: ${((loaded / total) * 100).toFixed(1)}%`);
};
manager.onLoad = () => {
console.log("All assets loaded");
};
manager.onError = (url) => {
console.error(`Error loading: ${url}`);
};
const gltfLoader = new GLTFLoader(manager);
const textureLoader = new THREE.TextureLoader(manager);
// onLoad fires when every tracked item has finished
await Promise.all([
gltfLoader.loadAsync("model.glb"),
textureLoader.loadAsync("texture.jpg"),
textureLoader.loadAsync("normal.jpg"),
]);`manager.abort()` cancels in-flight requests for loaders that load through FileLoader (models, HDR, EXR, KTX2). Loaders that load through an HTML image element, such as TextureLoader, ignore it.
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
const manager = new THREE.LoadingManager();
const timeoutId = setTimeout(() => manager.abort(), 30000);
try {
const gltf = await new GLTFLoader(manager).loadAsync("model.glb");
scene.add(gltf.scene);
} catch (error) {
console.error(error);
} finally {
clearTimeout(timeoutId);
}`TextureLoader.load()` returns the texture immediately and fills it in when the image decodes; assign it right away and the first render picks it up. Adding a map to a material that has already rendered without one needs `material.needsUpdate = true`. `onProgress` is never called for image loading.
new THREE.TextureLoader().load(
"texture.jpg",
(map) => {
map.colorSpace = THREE.SRGBColorSpace; // a color map; scalar maps keep NoColorSpace
mesh.material.map = map;
mesh.material.needsUpdate = true; // the material rendered without a map before
},
undefined, // onProgress: not supported for image loading
(error) => {
console.error("Could not load texture", error);
},
);const map = new THREE.TextureLoader().load("color.jpg");
map.colorSpace = THREE.SRGBColorSpace; // LDR color images; scalar maps keep NoColorSpace
map.wrapS = THREE.RepeatWrapping; // ClampToEdgeWrapping (default), RepeatWrapping, MirroredRepeatWrapping
map.wrapT = THREE.RepeatWrapping;
map.repeat.set(2, 2);
map.offset.set(0.5, 0.5);
map.rotation = Math.PI / 4;
map.center.set(0.5, 0.5);
map.minFilter = THREE.LinearMipmapLinearFilter; // default
map.magFilter = THREE.LinearFilter; // default; NearestFilter for a pixelated look
map.anisotropy = renderer.capabilities.getMaxAnisotropy(); // sharper textures at grazing angles
mesh.material.map = map;
// wrap, filters, anisotropy, colorSpace and flipY (true by default) apply at upload: set them before the first render or set map.needsUpdate = true; repeat, offset, rotation and center apply every frameColor spaces: LDR color images (albedo, emissive) are `SRGBColorSpace`; scalar maps (normal, bump, roughness, metalness, ao, alpha) keep the default `NoColorSpace`. GLTFLoader sets the correct color spaces for the textures it loads, and the HDR loaders below set `LinearSRGBColorSpace` themselves. A texture you load yourself for a glTF model's material needs `map.flipY = false` to match the textures GLTFLoader loads.
For skyboxes and cube environments, six faces in +X, -X, +Y, -Y, +Z, -Z order; the loader sets sRGB itself.
const cubeTexture = await new THREE.CubeTextureLoader().loadAsync([ "px.jpg", "nx.jpg", "py.jpg", "ny.jpg", "pz.jpg", "nz.jpg", ]); scene.background = cubeTexture; scene.environment = cubeTexture;
`HDRLoader` (Radiance `.hdr`) and `EXRLoader` return floating-point equirectangular textures. Both renderers prefilter an equirectangular environment themselves, so no PMREM step is needed for a file — set `mapping` and assign it.
import { HDRLoader } from "three/addons/loaders/HDRLoader.js";
import { EXRLoader } from "three/addons/loaders/EXRLoader.js";
const env = await new HDRLoader().loadAsync("environment.hdr");
env.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = env;
scene.background = env; // without mapping, a background texture draws as a flat screen quad
conSkill 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…
Light types and physical units, shadow maps, HDR environment lighting, light probes, and lighting performance, on WebGL or with…
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…