threejs-loaders

Three.js asset loading - GLTF, textures, images, models, async patterns. Use when loading 3D models, textures, HDR environments, or managing loading progress.

By cloudai-x · 8,208 installs

npx skills add cloudai-x/threejs-skills --skill threejs-loaders

Source repository · Upstream listing

Three.js Loaders Targets three.js r186. Examples use WebGLRenderer; the WebGPU and TSL section uses WebGPURenderer. Quick Start LoadingManager One manager coordinates several loaders and reports combined progress. loadAsync still rejects on failure; manager.onError fires as well. 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. 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. Texture configuration 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. 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. Dim the environment with scene.environmentIntensity (and rotate it with scene.environmentRotation ); material.envMapIntensity scales only a material's own envMap , which stays null on models lit by scene.environment . UltraHDRLoader reads gain map JPEGs — HDR dynamic range at JPEG file sizes — the same way: Use PMREMGenerator for generated environments, not files: glTF and GLB The primary format for web delivery. The result carries scene , animations , cameras , asset (version, generator) and userData (authoring custom data). Draco, meshopt and KTX2 compression The Draco decoder and the Basis transcoder load from the three package by default; call setDecoderPath / setTranscoderPath only when you host them yourself, and then pin the path to the three release you ship. A file that requires EXT meshopt compression or KHR meshopt compression fails to load unless setMeshoptDecoder is set. Processing loaded content Other Model Formats OBJ + MTL FBX STL PLY The loader honors the file's data types, so double properties arrive as attributes backed by a Float64Array , which WebGLRenderer cannot upload; convert them to Float32BufferAttribute before rendering. USD Async Patterns and Custom Sources Load independent assets in parallel: Parse data you already hold (a downloaded file, a file input, a database record): Blob URLs and data URLs work as loader URLs: Prefix paths and rewrite URLs through the manager: Enable the shared cache to serve repeated URLs from memory: Keep payloads small — Draco or meshopt for geometry, KTX2 for textures, produced as in threejs asset pipeline — and show a placeholder mesh while the real model loads, swapping it in once loading resolves. Cloning and Disposal Object3D.clone() on a skinned model shares the skeleton: every copy stays bound to the original's bones, so copies follow the original and ignore their own animation. Use SkeletonUtils.clone() for instances. object.dispose() frees renderer side state for that object only (WebGPU bindings, InstancedMesh buffers) and does not visit children or dispose geometry, materials or textures — traverse the subtree: WebGPU and TSL ktx2Loader.detectSupport(renderer) and the PMREMGenerator methods ( fromScene , fromEquirectangular , fromCubemap ) throw before await renderer.init() . Max anisotropy is renderer.getMaxAnisotropy() ; renderer.capabilities does not exist under WebGPURenderer. Gaussian splats: SPLATLoader , SPZLoader , KSPLATLoader and GaussianSplatPLYLoader load data for new GaussianSplat(data) from three/addons/objects/GaussianSplat.js , which requires WebGPURenderer. Common Mistakes import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js" → import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js" : the three/examples/jsm/ specifier does not resolve under the import map three.js documents. import { RGBELoader } from "three/addons/loaders/RGBELoader.js" → import { HDRLoader } from "three/addons/loaders/HDRLoader.js" : renamed from RGBELoader in r180; the old class warns on every construction. new Promise((resolve, reject) = loader.load(url, resolve, undefined, reject)) → loader.loadAsync(url) : every loader already implements loadAsync, which rejects on error. material.map = new THREE.TextureLoader().load("color.jpg") → const map = new THREE.TextureLoader().load("color.jpg"); map.colorSpace = THREE.SRGBColorSpace; material.map = map; : a loaded color map defaults to NoColorSpace and renders washed out. normalMap.colorSpace = THREE.LinearSRGBColorSpace → normalMap.colorSpace = THREE.NoColorSpace : scalar maps (normal, bump, roughness, metalness, ao, alpha) keep NoColorSpace; LinearSRGBColorSpace is for linear color data. texture.encoding = THREE.sRGBEncoding → texture.colorSpace = THREE.SRGBColorSpace : encoding and sRGBEncoding no longer exist, so the old line leaves the map at NoColorSpace and it renders washed out. child.material.envMapIntensity = 0.5 → scene.environmentIntensity = 0.5 : envMapIntensity scales only material.envMap, which stays null when the model is lit by scene.environment. scene.environment = pmremGenerator.fromEquirectangular(hdrTexture).texture → hdrTexture.mapping = THREE.EquirectangularReflectionMapping; scene.environment = hdrTexture; : both renderers run that PMREM step themselves for an equirectangular texture, so the manual pass only adds code and a render target to dispose. scene.background = hdrTexture → hdrTexture.mapping = THREE.EquirectangularReflectionMapping; scene.background = hdrTexture; : without the mapping, a background texture draws as a flat screen quad. ktx2Loader.setTranscoderPath(pathFromAnotherRelease) → const ktx2Loader = new KTX2Loader().detectSupport(renderer) : the Basis transcoder and the Draco decoder load from the three package by default; a path pinned to another release mismatches the loader. ktx2Loader.detectSupportAsync(renderer) → await renderer.init(); ktx2Loader.detectSupport(renderer); : detectSupportAsync is deprecated in r181; call detectSupport once the renderer is initialized. renderer.capabilities.getMaxAnisotropy() → renderer.getMaxAnisotropy() : capabilities exists on WebGLRenderer only; under WebGPURenderer use the renderer method. scene.add(new THREE.Mesh(await new PLYLoader().loadAsync("scan.ply"), material)) → const geometry = await new PLYLoader().loadAsync("scan.ply"); for (const [name, a] of Object.entries(geometry.attributes)) if (a.array instanceof Float64Array) geometry.setAttribute(name, new THREE.Float32BufferAttribute(a.array, a.itemSize)); scene.add(new THREE.Mesh(geometry, material)); : PLYLoader keeps double properties as Float64 attributes, which WebGLRenderer cannot upload (it throws Unsupported buffer data format). gltf.scene.clone() → SkeletonUtils.clone(gltf.scene) : Object3D.clone() shares the skeleton, so every copy stays bound to the original's bones and follows its animation. gltf.scene.dispose() → gltf.scene.traverse((child) = { child.geometry?.dispose(); for (const material of [child.material ?? []].flat()) { for (const value of Object.values(material)) if (value?.isTexture) value.dispose(); material.dispose(); } child.dispose(); }) : Object3D.dispose() frees renderer state for that object only, never its geometry, materials or textures, and material.dispose() does not free the material's textures. fetch(url, { signal: controller.signal }) → setTimeout(() = manager.abort(), 30000) : loaders are cancelled through their LoadingManager, which aborts in flight FileLoader requests. new USDZLoader() → new USDLoader() : deprecated in r179; USDLoader reads USD, USDA, USDC and USDZ. See Also threejs fundamentals renderer setup, resize handling and the app scaffold around loaded assets threejs textures and threejs materials texture properties and color spaces, and adjusting the materials loaded models come with threejs asset pipeline compressing and optimizing glTF files before they reach these loaders threejs animation AnimationMixer, clips and skinned mesh playback