Threejs Textures

CloudAI-X/threejs-skills/skills/threejs-textures

by CloudAI-Xb1c623076c661fc9b03dac19292e825a5d106823No license3.4K starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated 3 months ago

Three.js textures - texture types, UV mapping, environment maps, texture settings. Use when working with images, UV coordinates, cubemaps, HDR environments, or texture optimization.

Instructions onlySoftware Development
AI-generated overview

Reference guide for Three.js textures: loading, configuration, UV mapping, environment maps and optimization.

What it does
This skill provides code-oriented reference material for working with textures in Three.js. It covers texture loading, color space and filtering settings, wrapping, repeat and offset, data, canvas and video textures, cube and HDR environment maps, render targets, UV mapping, texture atlases, PBR material maps, procedural textures and memory management. It produces explanatory snippets and guidance rather than executable scripts.
When to use it
Use it when writing or reviewing Three.js code that involves images, UV coordinates, cubemaps, HDR environments or texture performance tuning. It suits questions about texture configuration, material maps and texture disposal.
Requirements
No scripts are shipped; it is instructions only. Using the examples assumes a JavaScript project with the three package and, for compressed or HDR textures, the corresponding Three.js example loaders.

Three.js Textures

Quick Start

javascript
import * as THREE from "three";
// Load textureconst loader = new THREE.TextureLoader();const texture = loader.load("texture.jpg");
// Apply to materialconst material = new THREE.MeshStandardMaterial({  map: texture,});

Texture Loading

Basic Loading

javascript
const loader = new THREE.TextureLoader();
// Async with callbacksloader.load(  "texture.jpg",  (texture) => console.log("Loaded"),  (progress) => console.log("Progress"),  (error) => console.error("Error"),);
// Synchronous style (loads async internally)const texture = loader.load("texture.jpg");material.map = texture;

Promise Wrapper

javascript
function loadTexture(url) {  return new Promise((resolve, reject) => {    new THREE.TextureLoader().load(url, resolve, undefined, reject);  });}
// Usageconst [colorMap, normalMap, roughnessMap] = await Promise.all([  loadTexture("color.jpg"),  loadTexture("normal.jpg"),  loadTexture("roughness.jpg"),]);

Texture Configuration

Color Space

Critical for accurate color reproduction.

javascript
// Color/albedo textures - use sRGBcolorTexture.colorSpace = THREE.SRGBColorSpace;
// Data textures (normal, roughness, metalness, AO) - leave as default// Do NOT set colorSpace for data textures (NoColorSpace is default)

Wrapping Modes

javascript
texture.wrapS = THREE.RepeatWrapping; // Horizontaltexture.wrapT = THREE.RepeatWrapping; // Vertical
// Options:// THREE.ClampToEdgeWrapping - Stretches edge pixels (default)// THREE.RepeatWrapping - Tiles the texture// THREE.MirroredRepeatWrapping - Tiles with mirror flip

Repeat, Offset, Rotation

javascript
// Tile texture 4x4texture.repeat.set(4, 4);texture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;
// Offset (0-1 range)texture.offset.set(0.5, 0.5);
// Rotation (radians, around center)texture.rotation = Math.PI / 4;texture.center.set(0.5, 0.5); // Rotation pivot

Filtering

javascript
// Minification (texture larger than screen pixels)texture.minFilter = THREE.LinearMipmapLinearFilter; // Default, smoothtexture.minFilter = THREE.NearestFilter; // Pixelatedtexture.minFilter = THREE.LinearFilter; // Smooth, no mipmaps
// Magnification (texture smaller than screen pixels)texture.magFilter = THREE.LinearFilter; // Smooth (default)texture.magFilter = THREE.NearestFilter; // Pixelated (retro games)
// Anisotropic filtering (sharper at angles)texture.anisotropy = renderer.capabilities.getMaxAnisotropy();

Generate Mipmaps

javascript
// Usually true by defaulttexture.generateMipmaps = true;
// Disable for non-power-of-2 textures or data texturestexture.generateMipmaps = false;texture.minFilter = THREE.LinearFilter;

Texture Types

Regular Texture

javascript
const texture = new THREE.Texture(image);texture.needsUpdate = true;

Data Texture

Create texture from raw data.

javascript
// Create gradient textureconst size = 256;const data = new Uint8Array(size * size * 4);
for (let i = 0; i < size; i++) {  for (let j = 0; j < size; j++) {    const index = (i * size + j) * 4;    data[index] = i; // R    data[index + 1] = j; // G    data[index + 2] = 128; // B    data[index + 3] = 255; // A  }}
const texture = new THREE.DataTexture(data, size, size);texture.needsUpdate = true;

Canvas Texture

javascript
const canvas = document.createElement("canvas");canvas.width = 256;canvas.height = 256;const ctx = canvas.getContext("2d");
// Draw on canvasctx.fillStyle = "red";ctx.fillRect(0, 0, 256, 256);ctx.fillStyle = "white";ctx.font = "48px Arial";ctx.fillText("Hello", 50, 150);
const texture = new THREE.CanvasTexture(canvas);
// Update when canvas changestexture.needsUpdate = true;

Video Texture

javascript
const video = document.createElement("video");video.src = "video.mp4";video.loop = true;video.muted = true;video.play();
const texture = new THREE.VideoTexture(video);texture.colorSpace = THREE.SRGBColorSpace;
// No need to set needsUpdate - auto-updates

Compressed Textures

javascript
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
const ktx2Loader = new KTX2Loader();ktx2Loader.setTranscoderPath("path/to/basis/");ktx2Loader.detectSupport(renderer);
ktx2Loader.load("texture.ktx2", (texture) => {  material.map = texture;});

Cube Textures

For environment maps and skyboxes.

CubeTextureLoader

javascript
const loader = new THREE.CubeTextureLoader();const cubeTexture = loader.load([  "px.jpg",  "nx.jpg", // +X, -X  "py.jpg",  "ny.jpg", // +Y, -Y  "pz.jpg",  "nz.jpg", // +Z, -Z]);
// As backgroundscene.background = cubeTexture;
// As environment mapscene.environment = cubeTexture;material.envMap = cubeTexture;

Equirectangular to Cubemap

javascript
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
const pmremGenerator = new THREE.PMREMGenerator(renderer);pmremGenerator.compileEquirectangularShader();
new RGBELoader().load("environment.hdr", (texture) => {  const envMap = pmremGenerator.fromEquirectangular(texture).texture;  scene.environment = envMap;  scene.background = envMap;
  texture.dispose();  pmremGenerator.dispose();});

HDR Textures

RGBELoader

javascript
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
const loader = new RGBELoader();loader.load("environment.hdr", (texture) => {  texture.mapping = THREE.EquirectangularReflectionMapping;  scene.environment = texture;  scene.background = texture;});

EXRLoader

javascript
import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
const loader = new EXRLoader();loader.load("environment.exr", (texture) => {  texture.mapping = THREE.EquirectangularReflectionMapping;  scene.environment = texture;});

Background Options

javascript
scene.background = texture;scene.backgroundBlurriness = 0.5; // 0-1, blur backgroundscene.backgroundIntensity = 1.0; // Brightnessscene.backgroundRotation.y = Math.PI; // Rotate background

Render Targets

Render to texture for effects.

javascript
// Create render targetconst renderTarget = new THREE.WebGLRenderTarget(512, 512, {  minFilter: THREE.LinearFilter,  magFilter: THREE.LinearFilter,  format: THREE.RGBAFormat,});
// Render scene to targetrenderer.setRenderTarget(renderTarget);renderer.render(scene, camera);renderer.setRenderTarget(null); // Back to screen
// Use as texturematerial.map = renderTarget.texture;

Depth Texture

javascript
const renderTarget = new THREE.WebGLRenderTarget(512, 512);renderTarget.depthTexture = new THREE.DepthTexture(  512,  512,  THREE.UnsignedShortType,);
// Access depthconst depthTexture = renderTarget.depthTexture;

Multi-Sample Render Target

javascript
const renderTarget = new THREE.WebGLRenderTarget(512, 512, {  samples: 4, // MSAA});

CubeCamera

Dynamic environment maps for reflections.

javascript
const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(256, {  generateMipmaps: true,  minFilter: THREE.LinearMipmapLinearFilter,});
const cubeCamera = new THREE.CubeCamera(0.1, 1000, cubeRenderTarget);scene.add(cubeCamera);
// Apply to reflective materialreflectiveMaterial.envMap = cubeRenderTarget.texture;
// Update in animation loop (expensive!)function animate() {  // Hide reflective object, update env map, show again  reflectiveObject.visible = false;  cubeCamera.position.copy(reflectiveObject.position);  cubeCamera.update(renderer, scene);  reflectiveObject.visible = true;}

UV Mapping

Accessing UVs

javascript
const uvs = geometry.attributes.uv;
// Read UVconst u = uvs.getX(vertexIndex);const v = uvs.getY(vertexIndex);
// Modify UVuvs.setXY(vertexIndex, newU, newV);uvs.needsUpdate = true;

Second UV Channel (for AO maps)

javascript
// Required for aoMapgeometry.setAttribute("uv2", geometry.attributes.uv);
// Or create custom second UVconst uv2 = new Float32Array(vertexCount * 2);// ... fill uv2 datageometry.setAttribute("uv2", new THREE.BufferAttribute(uv2, 2));

UV Transform in Shader

javascript
const material = new THREE.ShaderMaterial({  uniforms: {    map: { value: texture },    uvOffset: { value: new THREE.Vector2(0, 0) },    uvScale: { value: new THREE.Vector2(1, 1) },  },  vertexShader: `    varying vec2 vUv;    uniform vec2 uvOffset;    uniform vec2 uvScale;
    void main() {      vUv = uv * uvScale + uvOffset;      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);    }  `,  fragmentShader: `    varying vec2 vUv;    uniform sampler2D map;
    void main() {      gl_FragColor = texture2D(map, vUv);    }  `,});

Texture Atlas

Multiple images in one texture.

javascript
// Atlas with 4 sprites (2x2 grid)const atlas = loader.load("atlas.png");atlas.wrapS = THREE.ClampToEdgeWrapping;atlas.wrapT = THREE.ClampToEdgeWrapping;
// Select sprite by UV offset/scalefunction selectSprite(row, col, gridSize = 2) {  atlas.offset.set(col / gridSize, 1 - (row + 1) / gridSize);  atlas.repeat.set(1 / gridSize, 1 / gridSize);}
// Select top-left spriteselectSprite(0, 0);

Material Texture Maps

PBR Texture Set

javascript
const material = new THREE.MeshStandardMaterial({  // Base color (sRGB)  map: colorTexture,
  // Surface detail (Linear)  normalMap: normalTexture,  normalScale: new THREE.Vector2(1, 1),
  // Roughness (Linear, grayscale)  roughnessMap: roughnessTexture,  roughness: 1, // Multiplier
  // Metalness (Linear, grayscale)  metalnessMap: metalnessTexture,  metalness: 1, // Multiplier
  // Ambient occlusion (Linear, uses uv2)  aoMap: aoTexture,  aoMapIntensity: 1,
  // Self-illumination (sRGB)  emissiveMap: emissiveTexture,  emissive: 0xffffff,  emissiveIntensity: 1,
  // Vertex displacement (Linear)  displacementMap: displacementTexture,  displacementScale: 0.1,  displacementBias: 0,
  // Alpha (Linear)  alphaMap: alphaTexture,  transparent: true,});
// Don't forget UV2 for AOgeometry.setAttribute("uv2", geometry.attributes.uv);

Normal Map Types

javascript
// OpenGL style normals (default)material.normalMapType = THREE.TangentSpaceNormalMap;
// Object space normalsmaterial.normalMapType = THREE.ObjectSpaceNormalMap;

Procedural Textures

Noise Texture

javascript
function generateNoiseTexture(size = 256) {  const data = new Uint8Array(size * size * 4);
  for (let i = 0; i < size * size; i++) {    const value = Math.random() * 255;    data[i * 4] = value;    data[i * 4 + 1] = value;    data[i * 4 + 2] = value;    data[i * 4 + 3] = 255;  }
  const texture = new THREE.DataTexture(data, size, size);  texture.needsUpdate = true;  return texture;}

Gradient Texture

javascript
function generateGradientTexture(color1, color2, size = 256) {  const canvas = document.createElement("canvas");  canvas.width = size;  canvas.height = 1;  const ctx = canvas.getContext("2d");
  const gradient = ctx.createLinearGradient(0, 0, size, 0);  gradient.addColorStop(0, color1);  gradient.addColorStop(1, color2);
  ctx.fillStyle = gradient;  ctx.fillRect(0, 0, size, 1);
  return new THREE.CanvasTexture(canvas);}

Texture Memory Management

Dispose Textures

javascript
// Single texturetexture.dispose();
// Material texturesfunction disposeMaterial(material) {  const maps = [    "map",    "normalMap",    "roughnessMap",    "metalnessMap",    "aoMap",    "emissiveMap",    "displacementMap",    "alphaMap",    "envMap",    "lightMap",    "bumpMap",    "specularMap",  ];
  maps.forEach((mapName) => {    if (material[mapName]) {      material[mapName].dispose();    }  });
  material.dispose();}

Texture Pooling

javascript
class TexturePool {  constructor() {    this.textures = new Map();    this.loader = new THREE.TextureLoader();  }
  async get(url) {    if (this.textures.has(url)) {      return this.textures.get(url);    }
    const texture = await new Promise((resolve, reject) => {      this.loader.load(url, resolve, undefined, reject);    });
    this.textures.set(url, texture);    return texture;  }
  dispose(url) {    const texture = this.textures.get(url);    if (texture) {      texture.dispose();      this.textures.delete(url);    }  }
  disposeAll() {    this.textures.forEach((t) => t.dispose());    this.textures.clear();  }}

Performance Tips

  1. Use power-of-2 dimensions: 256, 512, 1024, 2048
  2. Compress textures: KTX2/Basis for web delivery
  3. Use texture atlases: Reduce texture switches
  4. Enable mipmaps: For distant objects
  5. Limit texture size: 2048 usually sufficient for web
  6. Reuse textures: Same texture = better batching
javascript
// Check texture memoryconsole.log(renderer.info.memory.textures);
// Optimize for mobileconst maxSize = renderer.capabilities.maxTextureSize;const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent);const textureSize = isMobile ? 1024 : 2048;

See Also

  • threejs-materials - Applying textures to materials
  • threejs-loaders - Loading texture files
  • threejs-shaders - Custom texture sampling

Source and attribution

Source:CloudAI-X/threejs-skillsinskills/threejs-texturesat commitb1c6230

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal