Three.js Textures
Use this skill for texture assets, UV behavior, color/data interpretation, environment
maps, and GPU texture memory. Route asset transport/decoder setup to threejs-loaders,
PBR material semantics to threejs-materials, and direct lighting decisions to
threejs-lighting.
When to use this skill
- Load and configure base-color, normal, roughness, metalness, AO, emissive, or alpha maps
- Fix color mismatch, blurry/distant images, seams, bad repeats, incorrect UVs, or missing AO
- Use HDR/cubemap environments, canvas/video/data textures, or render targets
- Reduce texture memory, resolution, sampling, or duplicated GPU allocations
Instructions
Step 1: Classify every texture by meaning
- Identify whether the texture stores visible color or non-color data.
- Use the renderer/version's documented color-space settings for visible color textures;
do not apply display color treatment to normal, roughness, metalness, depth, or data maps.
- Confirm the mesh has the UV channel the material map expects. Ambient occlusion often
needs a second UV set depending on the material and asset pipeline.
const baseColor = await new THREE.TextureLoader().loadAsync("/textures/albedo.jpg");
baseColor.colorSpace = THREE.SRGBColorSpace;
baseColor.wrapS = THREE.RepeatWrapping;
baseColor.wrapT = THREE.RepeatWrapping;
baseColor.repeat.set(2, 2);
Step 2: Choose sampling and wrapping from visual evidence
| Need |
Setting direction |
| Tileable map |
Repeat/mirrored wrapping and intentional repeat |
| Hard pixel-art texture |
Nearest filtering, no accidental mip blur |
| Normal 3D asset |
Mipmaps plus appropriate min/mag filtering |
| Oblique surface detail |
Anisotropy within measured device limits |
| Cutout alpha |
Correct material alpha policy, not texture filtering alone |
| Dynamic canvas/video |
CanvasTexture / VideoTexture with lifecycle control |
Do not set maximum anisotropy globally by habit. Query hardware capability and use a
quality tier based on actual visual value.
Step 3: Handle environment and render textures as GPU resources
An HDR/equirectangular texture generally requires the renderer-version-appropriate
preprocessing path before use as a PBR environment. Set scene.environment and
scene.background separately according to the intended effect. A render target's texture
is produced by a render pass and must be resized/disposed with that pass.
Step 4: Budget memory and ownership
Texture memory scales with dimensions, mip levels, format, and copies—not only file size.
Reuse immutable texture instances, avoid loading the same URL through multiple owners, and
release feature-owned textures/render targets when their last user unmounts.
function disposeTexture(texture) {
texture?.dispose();
}
Do not dispose a texture held by another material or shared asset cache.
Step 5: Verify visual correctness and lifecycle
- Test base-color, normal, roughness, metalness, AO, and emissive maps under representative
lights and color management.
- Inspect UV seams and repeat orientation on the actual mesh.
- Test the target device/profile for memory pressure and frame-time behavior.
- Resize render targets, stop/release video resources, and dispose feature-owned GPU textures.
Examples
PBR texture set
Wire each map to its semantic material property, set color space only for visible color
maps, and validate the asset's normal-map convention. A flat or inverted normal look is
usually map convention, tangent/UV, or color-data handling—not a roughness issue.
Dynamic video surface
Create VideoTexture from an explicitly owned video element, handle play/pause/error and
cross-origin setup, and dispose the texture plus media resource according to the UI lifecycle.
Best practices
- Distinguish display color from numeric data before setting color space.
- Keep UV channel expectations explicit in the asset pipeline.
- Use texture dimensions and compression appropriate to the device budget.
- Reuse shared textures and dispose only when their final consumer is gone.
- Treat render targets and video/canvas textures as active lifecycle resources.
References
1---2name: threejs-textures3description: Load, configure, and optimize Three.js textures: color space, wrapping, filtering, mipmaps, UV transforms, normal/AO/PBR maps, cube and HDR environments, data/canvas/video textures, render targets, texture memory, and disposal. Use when images look wrong, UVs repeat incorrectly, HDR/IBL is needed, or texture quality and GPU memory need tuning. Triggers on: Three.js texture, TextureLoader, UV mapping, color space, sRGB, mipmap, anisotropy, normal map, environment map, cubemap, HDR texture, render target, video texture.4license: MIT5---67# Three.js Textures89Use this skill for texture assets, UV behavior, color/data interpretation, environment10maps, and GPU texture memory. Route asset transport/decoder setup to `threejs-loaders`,11PBR material semantics to `threejs-materials`, and direct lighting decisions to12`threejs-lighting`.1314## When to use this skill1516- Load and configure base-color, normal, roughness, metalness, AO, emissive, or alpha maps17- Fix color mismatch, blurry/distant images, seams, bad repeats, incorrect UVs, or missing AO18- Use HDR/cubemap environments, canvas/video/data textures, or render targets19- Reduce texture memory, resolution, sampling, or duplicated GPU allocations2021## Instructions2223### Step 1: Classify every texture by meaning24251. Identify whether the texture stores visible color or non-color data.262. Use the renderer/version's documented color-space settings for visible color textures;27 do not apply display color treatment to normal, roughness, metalness, depth, or data maps.283. Confirm the mesh has the UV channel the material map expects. Ambient occlusion often29 needs a second UV set depending on the material and asset pipeline.3031```js32const baseColor = await new THREE.TextureLoader().loadAsync("/textures/albedo.jpg");33baseColor.colorSpace = THREE.SRGBColorSpace;34baseColor.wrapS = THREE.RepeatWrapping;35baseColor.wrapT = THREE.RepeatWrapping;36baseColor.repeat.set(2, 2);37```3839### Step 2: Choose sampling and wrapping from visual evidence4041| Need | Setting direction |42|---|---|43| Tileable map | Repeat/mirrored wrapping and intentional `repeat` |44| Hard pixel-art texture | Nearest filtering, no accidental mip blur |45| Normal 3D asset | Mipmaps plus appropriate min/mag filtering |46| Oblique surface detail | Anisotropy within measured device limits |47| Cutout alpha | Correct material alpha policy, not texture filtering alone |48| Dynamic canvas/video | `CanvasTexture` / `VideoTexture` with lifecycle control |4950Do not set maximum anisotropy globally by habit. Query hardware capability and use a51quality tier based on actual visual value.5253### Step 3: Handle environment and render textures as GPU resources5455An HDR/equirectangular texture generally requires the renderer-version-appropriate56preprocessing path before use as a PBR environment. Set `scene.environment` and57`scene.background` separately according to the intended effect. A render target's texture58is produced by a render pass and must be resized/disposed with that pass.5960### Step 4: Budget memory and ownership6162Texture memory scales with dimensions, mip levels, format, and copies—not only file size.63Reuse immutable texture instances, avoid loading the same URL through multiple owners, and64release feature-owned textures/render targets when their last user unmounts.6566```js67function disposeTexture(texture) {68 texture?.dispose();69}70```7172Do not dispose a texture held by another material or shared asset cache.7374### Step 5: Verify visual correctness and lifecycle7576- Test base-color, normal, roughness, metalness, AO, and emissive maps under representative77 lights and color management.78- Inspect UV seams and repeat orientation on the actual mesh.79- Test the target device/profile for memory pressure and frame-time behavior.80- Resize render targets, stop/release video resources, and dispose feature-owned GPU textures.8182## Examples8384### PBR texture set8586Wire each map to its semantic material property, set color space only for visible color87maps, and validate the asset's normal-map convention. A flat or inverted normal look is88usually map convention, tangent/UV, or color-data handling—not a roughness issue.8990### Dynamic video surface9192Create `VideoTexture` from an explicitly owned video element, handle play/pause/error and93cross-origin setup, and dispose the texture plus media resource according to the UI lifecycle.9495## Best practices96971. Distinguish display color from numeric data before setting color space.982. Keep UV channel expectations explicit in the asset pipeline.993. Use texture dimensions and compression appropriate to the device budget.1004. Reuse shared textures and dispose only when their final consumer is gone.1015. Treat render targets and video/canvas textures as active lifecycle resources.102103## References104105- [Three.js Textures source coverage](https://github.com/CloudAI-X/threejs-skills/tree/main/skills/threejs-textures)106- [Texture documentation](https://threejs.org/docs/#api/en/textures/Texture)107- [Three.js manual: textures](https://threejs.org/manual/#en/textures)