threejs-textures

import * as THREE from "three";

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "threejs-textures" with this command: npx skills add toilahuongg/shopify-agents-kit/toilahuongg-shopify-agents-kit-threejs-textures

Three.js Textures

Quick Start

import * as THREE from "three";

// Load texture const loader = new THREE.TextureLoader(); const texture = loader.load("texture.jpg");

// Apply to material const material = new THREE.MeshStandardMaterial({ map: texture, });

Texture Loading

Basic Loading

const loader = new THREE.TextureLoader();

// Async with callbacks loader.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

function loadTexture(url) { return new Promise((resolve, reject) => { new THREE.TextureLoader().load(url, resolve, undefined, reject); }); }

// Usage const [colorMap, normalMap, roughnessMap] = await Promise.all([ loadTexture("color.jpg"), loadTexture("normal.jpg"), loadTexture("roughness.jpg"), ]);

Texture Configuration

Color Space

Critical for accurate color reproduction.

// Color/albedo textures - use sRGB colorTexture.colorSpace = THREE.SRGBColorSpace;

// Data textures (normal, roughness, metalness, AO) - leave as default // Do NOT set colorSpace for data textures (NoColorSpace is default)

Wrapping Modes

texture.wrapS = THREE.RepeatWrapping; // Horizontal texture.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

// Tile texture 4x4 texture.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

// Minification (texture larger than screen pixels) texture.minFilter = THREE.LinearMipmapLinearFilter; // Default, smooth texture.minFilter = THREE.NearestFilter; // Pixelated texture.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

// Usually true by default texture.generateMipmaps = true;

// Disable for non-power-of-2 textures or data textures texture.generateMipmaps = false; texture.minFilter = THREE.LinearFilter;

Texture Types

Regular Texture

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

Data Texture

Create texture from raw data.

// Create gradient texture const 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

const canvas = document.createElement("canvas"); canvas.width = 256; canvas.height = 256; const ctx = canvas.getContext("2d");

// Draw on canvas ctx.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 changes texture.needsUpdate = true;

Video Texture

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

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

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 background scene.background = cubeTexture;

// As environment map scene.environment = cubeTexture; material.envMap = cubeTexture;

Equirectangular to Cubemap

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

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

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

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

Render Targets

Render to texture for effects.

// Create render target const renderTarget = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, });

// Render scene to target renderer.setRenderTarget(renderTarget); renderer.render(scene, camera); renderer.setRenderTarget(null); // Back to screen

// Use as texture material.map = renderTarget.texture;

Depth Texture

const renderTarget = new THREE.WebGLRenderTarget(512, 512); renderTarget.depthTexture = new THREE.DepthTexture( 512, 512, THREE.UnsignedShortType, );

// Access depth const depthTexture = renderTarget.depthTexture;

Multi-Sample Render Target

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

CubeCamera

Dynamic environment maps for reflections.

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 material reflectiveMaterial.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

const uvs = geometry.attributes.uv;

// Read UV const u = uvs.getX(vertexIndex); const v = uvs.getY(vertexIndex);

// Modify UV uvs.setXY(vertexIndex, newU, newV); uvs.needsUpdate = true;

Second UV Channel (for AO maps)

// Required for aoMap geometry.setAttribute("uv2", geometry.attributes.uv);

// Or create custom second UV const uv2 = new Float32Array(vertexCount * 2); // ... fill uv2 data geometry.setAttribute("uv2", new THREE.BufferAttribute(uv2, 2));

UV Transform in Shader

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.

// 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/scale function selectSprite(row, col, gridSize = 2) { atlas.offset.set(col / gridSize, 1 - (row + 1) / gridSize); atlas.repeat.set(1 / gridSize, 1 / gridSize); }

// Select top-left sprite selectSprite(0, 0);

Material Texture Maps

PBR Texture Set

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 AO geometry.setAttribute("uv2", geometry.attributes.uv);

Normal Map Types

// OpenGL style normals (default) material.normalMapType = THREE.TangentSpaceNormalMap;

// Object space normals material.normalMapType = THREE.ObjectSpaceNormalMap;

Procedural Textures

Noise Texture

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

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

// Single texture texture.dispose();

// Material textures function 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

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

  • Use power-of-2 dimensions: 256, 512, 1024, 2048

  • Compress textures: KTX2/Basis for web delivery

  • Use texture atlases: Reduce texture switches

  • Enable mipmaps: For distant objects

  • Limit texture size: 2048 usually sufficient for web

  • Reuse textures: Same texture = better batching

// Check texture memory console.log(renderer.info.memory.textures);

// Optimize for mobile const 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 Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

shopify-api

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

shopify-extensions

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

shopify-functions

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

agent-creator

No summary provided by upstream source.

Repository SourceNeeds Review