🎯

threejs-textures

🎯Skill

from toilahuongg/shopify-agents-kit

VibeIndex|
What it does

Loads, configures, and applies textures in Three.js with advanced options for color space, wrapping, tiling, and performance optimization.

πŸ“¦

Part of

toilahuongg/shopify-agents-kit(35 items)

threejs-textures

Installation

npm installInstall npm package
npm install -g shopify-cc-kit
npm installInstall npm package
npm install shopify-cc-kit
πŸ“– Extracted from docs: toilahuongg/shopify-agents-kit
1Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

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

Overview

# Three.js Textures

Quick Start

```javascript

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

```javascript

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

```javascript

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.

```javascript

// 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

```javascript

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

```javascript

// 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

```javascript

// 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

```javascript

// 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

```javascript

const texture = new THREE.Texture(image);

texture.needsUpdate = true;

```

Data Texture

Create texture from raw data.

```javascript

// 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

```javascript

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

```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 background

scene.background = cubeTexture;

// As environment map

scene.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 background

scene.backgroundIntensity = 1.0; // Brightness

scene.backgroundRotation.y = Math.PI; // Rotate background

```

Render Targets

Render to texture for effects.

```javascript

// 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

```javascript

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

```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 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

```javascript

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)

```javascript

// 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

```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/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

```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 AO

geometry.setAttribute("uv2", geometry.attributes.uv);

```

Normal Map Types

```javascript

// OpenGL style normals (default)

material.normalMapType = THREE.TangentSpaceNormalMap;

// Object space normals

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

```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 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

More from this repository10

🎯
shopify-polaris-icons🎯Skill

Provides comprehensive guidance and examples for integrating and using Shopify Polaris Icons in commerce applications with accessibility and semantic color tones.

🎯
shopify-polaris-viz🎯Skill

Generates accessible, Shopify Admin-styled data visualizations using Polaris Viz library for React applications.

🎯
shopify-polaris-design🎯Skill

Generates Shopify Polaris-styled React components and design elements for creating consistent and professional e-commerce interfaces.

🎯
threejs-loaders🎯Skill

Loads and manages 3D assets in Three.js, handling GLTF models, textures, and environments with comprehensive loading progress tracking.

🎯
brainstorm🎯Skill

Guides users through creative brainstorming by applying structured techniques like SCAMPER and Design Thinking to generate innovative solutions.

🎯
threejs-animation🎯Skill

Enables precise and flexible object animations in Three.js, supporting keyframe, skeletal, and procedural motion with advanced blending and playback control.

🎯
shopify-webhooks🎯Skill

Handles Shopify webhook verification, processing, and registration for real-time event synchronization with secure HMAC authentication.

🎯
shopify-extensions🎯Skill

Guides developers through building and integrating Shopify Extensions across Admin, Checkout, Theme, and Post-purchase interfaces using latest CLI and APIs.

🎯
design🎯Skill

Generates design-related tasks and recommendations for Shopify store aesthetics, layout, and visual branding using AI-powered analysis.

🎯
algorithmic-art🎯Skill

Generates algorithmic art philosophies and p5.js code sketches using computational aesthetics, seeded randomness, and generative design principles.