Threejs Textures

calesthio/OpenMontage/.agents/skills/threejs-textures

作者 calesthio9327439db69021ab4b0e2776729bf3b58fdb5a87無授權條款65K 個星標收錄於 2026年10月9日更新於 2026年10月9日儲存庫5 天前更新

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

AI 產生的概覽

Three.js 紋理參考指南:載入、設定、UV 對映、環境貼圖與最佳化。

功能
此技能提供在 Three.js 中處理紋理的程式碼參考內容。涵蓋紋理載入、色彩空間與濾波設定、環繞模式、重複與位移、資料紋理、畫布紋理與視訊紋理、立方體貼圖與 HDR 環境貼圖、算繪目標、UV 對映、紋理圖集、PBR 材質貼圖、程序化紋理以及記憶體管理。產出的是說明性程式碼片段與指引,而非可執行指令碼。
適用情境
在撰寫或檢閱涉及影像、UV 座標、立方體貼圖、HDR 環境或紋理效能調校的 Three.js 程式碼時使用。也適合紋理設定、材質貼圖與紋理釋放相關的問題。
執行需求
不隨附指令碼,僅為說明性內容。使用範例需具備包含 three 套件的 JavaScript 專案;處理壓縮紋理或 HDR 紋理時還需對應的 Three.js 範例載入器。

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

來源與署名

來源:calesthio/OpenMontage位於.agents/skills/threejs-textures提交9327439

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架