Skip to content
Frontend
Skill

/threejs-loaders

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

From plugin
threejs-skills
3.9k13 skills

Claude Code

$ npx -y skills add cloudai-x/threejs-skills --skill threejs-loaders --agent claude-code

SKILL.md

threejs-loaders.SKILL.md
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."

Three.js Loaders

Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer.

Quick Start

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

LoadingManager

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

Texture Loading

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

Texture configuration

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 frame

Color 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.

CubeTextureLoader

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;

HDR Environments

`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

con
Read more
@cloudai-x
Ships withthreejs-skills

Skill 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.

Stars on GitHub

Momentum

stars in total
3.9k
Star history of cloudai-x/threejs-skills on GitHub, a chart by star-history.com

Other skills on threejs-skills.

threejs-geometry

threejs-geometry

Creating and shaping three.js geometry: built-in shapes, 3D text, vertex buffers and attributes, merging, instancing, batching,…

threejs-lighting

threejs-lighting

Light types and physical units, shadow maps, HDR environment lighting, light probes, and lighting performance, on WebGL or with…

More skills from other plugins.

next-bundle-optimizer
Auto-invoked

next-bundle-optimizer

Audit and reduce Next.js browser initial-load work. Use for slow route startup, oversized client bundles, duplicate browser…

nextjstoday143k
@vercel@vercelInstall Skill
migrate-radix-to-base

migrate-radix-to-base

Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert…

ui10d127k
@shadcn-ui@shadcn-uiInstall Skill
chrome-release-cls

chrome-release-cls

Given a Chrome Releases blog post URL (chromereleases.googleblog.com), extract every CVE/bug and find the underlying Gerrit CL…

electrontoday124k
@electron@electronInstall Skill
taste-skill
Auto-invoked

taste-skill

tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One…

@leonxlnx@leonxlnxInstall Skill

Questions about threejs-loaders.

Which coding agents can use threejs-loaders?
threejs-loaders installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.