Skip to main content 홈 크리에이터 afovea game-dev-skills threejs-textures
threejs-textures Three.js texture loading and management — TextureLoader, colour spaces (SRGBColorSpace), wrapping modes, filtering, mipmaps, UV mapping, texture atlases, PBR texture sets (map/normalMap/roughnessMap/metalnessMap/aoMap/emissiveMap/displacementMap), video textures, canvas textures, DataTexture for procedural content, KTX2 compressed textures, and memory disposal. Use when loading or creating textures, configuring UV mapping, or managing texture memory. Adapted from CloudAI-X/threejs-skills (MIT).
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/afovea/game-dev-skills --skill threejs-textures명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... 이 저장소의 다른 Skills Art Director persona for visual style, pillars, art bible, cross-discipline visual consistency, art critique, and art QA. Use when a task needs visual direction, style enforcement, or cohesion across concept, environment, character, VFX, and lighting.
Audio Director persona for sound design, music direction, mix, audio implementation patterns, and audio pipeline. Use when a task needs reasoning about audio intent, audio-mechanic integration, mix balance, or the audio toolchain.
Post-pipeline cleanup and verification pass for game-development work. Regenerate / re-bake any derived content, rebuild the project, verify the editor / engine opens cleanly, run automated test suites, take a perf snapshot against budgets, and confirm save / network / cert / pipeline surfaces are untouched (or correctly versioned) against the pre-run baseline.
name threejs-textures description Three.js texture loading and management — TextureLoader, colour spaces (SRGBColorSpace), wrapping modes, filtering, mipmaps, UV mapping, texture atlases, PBR texture sets (map/normalMap/roughnessMap/metalnessMap/aoMap/emissiveMap/displacementMap), video textures, canvas textures, DataTexture for procedural content, KTX2 compressed textures, and memory disposal. Use when loading or creating textures, configuring UV mapping, or managing texture memory. Adapted from CloudAI-X/threejs-skills (MIT). license MIT compatibility Portable reference skill for agents that support markdown skills or prompt files. Works best alongside project Three.js source files and texture asset pipeline. disable-model-invocation true metadata {"owner":"game-delivery","version":"2.0.0","language":"en-GB","category":"web-rendering","upstream_references":["https://github.com/CloudAI-X/threejs-skills (MIT — see NOTICE.md)"],"tags":["three-js","textures","texture-loading","uv-mapping","pbr","normal-map","colour-space","video-texture","canvas-texture","ktx2","memory-management"],"intents":["texture-loading","colour-space-selection","uv-configuration","pbr-texture-set","texture-compression","memory-disposal"],"output_types":["code-example","api-reference","texture-budget"]}
Three.js Textures
Quick Start
import * as THREE from 'three' ;
const loader = new THREE .TextureLoader ();
const texture = loader.load ('diffuse.jpg' );
texture.colorSpace = THREE .SRGBColorSpace ;
const material = new THREE .MeshStandardMaterial ({ map : texture });
const mesh = new THREE .Mesh (new THREE .BoxGeometry (1 , 1 , 1 ), material);
scene.add (mesh);
TextureLoader
Basic Loading
const loader = new THREE .TextureLoader ();
loader.load (
'texture.jpg' ,
texture => { material.map = texture; material.needsUpdate = true ; },
undefined ,
=> . ( , err),
);
( ) {
( {
loader. (url, resolve, , reject);
});
}
texture = ( );
err
console
error
'Load error:'
async
function
loadTexture
url
return
new
Promise
(resolve, reject ) =>
load
undefined
const
await
loadTexture
'texture.jpg'
Loading Multiple Textures import { LoadingManager } from 'three' ;
const manager = new LoadingManager (
() => console .log ('All textures loaded' ),
(url, n, total ) => console .log (`${n} /${total} — ${url} ` ),
url => console .error (`Error: ${url} ` ),
);
const loader = new THREE .TextureLoader (manager);
const [diffuse, normal, roughness] = await Promise .all ([
loadTexture ('diffuse.jpg' ),
loadTexture ('normal.jpg' ),
loadTexture ('roughness.jpg' ),
]);
Colour Space Critical: colour textures must be tagged SRGBColorSpace; data textures must be LinearSRGBColorSpace.
texture.colorSpace = THREE .SRGBColorSpace ;
normalMap.colorSpace = THREE .LinearSRGBColorSpace ;
roughnessMap.colorSpace = THREE .LinearSRGBColorSpace ;
metalnessMap.colorSpace = THREE .LinearSRGBColorSpace ;
aoMap.colorSpace = THREE .LinearSRGBColorSpace ;
displacementMap.colorSpace = THREE .LinearSRGBColorSpace ;
renderer.outputColorSpace = THREE .SRGBColorSpace ;
Incorrect colour space causes washed-out or overly-dark materials.
Wrapping Modes texture.wrapS = THREE .RepeatWrapping ;
texture.wrapT = THREE .RepeatWrapping ;
texture.wrapS = THREE .ClampToEdgeWrapping ;
texture.wrapS = THREE .RepeatWrapping ;
texture.wrapS = THREE .MirroredRepeatWrapping ;
texture.repeat .set (4 , 4 );
texture.offset .set (0.5 , 0 );
texture.center .set (0.5 , 0.5 );
texture.rotation = Math .PI / 4 ;
Filtering and Mipmaps
texture.minFilter = THREE .LinearMipmapLinearFilter ;
texture.minFilter = THREE .NearestFilter ;
texture.minFilter = THREE .LinearFilter ;
texture.magFilter = THREE .LinearFilter ;
texture.magFilter = THREE .NearestFilter ;
const maxAniso = renderer.capabilities .getMaxAnisotropy ();
texture.anisotropy = maxAniso;
texture.generateMipmaps = false ;
texture.minFilter = THREE .LinearFilter ;
UV Mapping
Accessing UV Channels
geometry.setAttribute ('uv' , new THREE .BufferAttribute (uvArray, 2 ));
geometry.setAttribute ('uv2' , new THREE .BufferAttribute (uv2Array, 2 ));
const geo = new THREE .BoxGeometry (1 , 1 , 1 );
console .log (geo.attributes .uv );
UV Transform on Material
material.map .repeat .set (2 , 2 );
material.map .offset .set (0 , 0 );
material.aoMap .channel = 1 ;
PBR Texture Set (MeshStandardMaterial) const material = new THREE .MeshStandardMaterial ({
map : albedoTexture,
normalMap : normalTexture,
normalScale : new THREE .Vector2 (1 , 1 ),
roughnessMap : roughnessTexture,
roughness : 1.0 ,
metalnessMap : metalnessTexture,
metalness : 1.0 ,
aoMap : aoTexture,
aoMapIntensity : 1.0 ,
emissiveMap : emissiveTexture,
emissive : new THREE .Color (0xffffff ),
emissiveIntensity : 1.0 ,
displacementMap : heightTexture,
displacementScale : 0.1 ,
displacementBias : 0 ,
envMap : envMapTexture,
envMapIntensity : 1.0 ,
});
Packed ORM Texture (Optimised) Pack Occlusion (R), Roughness (G), Metalness (B) into one texture to save memory and sampling cost.
const ormTexture = loader.load ('orm.png' );
ormTexture.colorSpace = THREE .LinearSRGBColorSpace ;
const material = new THREE .MeshStandardMaterial ({
aoMap : ormTexture,
roughnessMap : ormTexture,
metalnessMap : ormTexture,
});
Video Texture Stream video frames as a texture. Update must be called in the render loop.
const video = document .createElement ('video' );
video.src = 'video.mp4' ;
video.loop = true ;
video.muted = true ;
video.play ();
const videoTexture = new THREE .VideoTexture (video);
videoTexture.colorSpace = THREE .SRGBColorSpace ;
const material = new THREE .MeshBasicMaterial ({ map : videoTexture });
function animate ( ) {
requestAnimationFrame (animate);
renderer.render (scene, camera);
}
Canvas Texture Use a <canvas> element as a texture — useful for dynamic text, HUD elements.
const canvas = document .createElement ('canvas' );
canvas.width = 512 ;
canvas.height = 256 ;
const ctx = canvas.getContext ('2d' );
ctx.fillStyle = '#000000' ;
ctx.fillRect (0 , 0 , canvas.width , canvas.height );
ctx.fillStyle = '#ffffff' ;
ctx.font = '48px Arial' ;
ctx.fillText ('Hello Three.js' , 50 , 150 );
const canvasTexture = new THREE .CanvasTexture (canvas);
function updateLabel (text ) {
ctx.clearRect (0 , 0 , canvas.width , canvas.height );
ctx.fillText (text, 50 , 150 );
canvasTexture.needsUpdate = true ;
}
DataTexture — Procedural Textures Create textures entirely in JavaScript without image assets.
const width = 256 ;
const height = 256 ;
const data = new Uint8Array (width * height * 4 );
for (let y = 0 ; y < height; y++) {
for (let x = 0 ; x < width; x++) {
const i = (y * width + x) * 4 ;
const value = Math .floor (Math .random () * 255 );
data[i] = value;
data[i + 1 ] = value;
data[i + 2 ] = value;
data[i + 3 ] = 255 ;
}
}
const dataTexture = new THREE .DataTexture (data, width, height, THREE .RGBAFormat );
dataTexture.needsUpdate = true ;
dataTexture.colorSpace = THREE .SRGBColorSpace ;
Checkerboard Pattern function createCheckerTexture (size = 128 , squareSize = 16 ) {
const data = new Uint8Array (size * size * 4 );
for (let y = 0 ; y < size; y++) {
for (let x = 0 ; x < size; x++) {
const i = (y * size + x) * 4 ;
const isWhite = (Math .floor (x / squareSize) + Math .floor (y / squareSize)) % 2 === 0 ;
const v = isWhite ? 255 : 50 ;
data[i] = data[i + 1 ] = data[i + 2 ] = v;
data[i + 3 ] = 255 ;
}
}
const tex = new THREE .DataTexture (data, size, size, THREE .RGBAFormat );
tex.needsUpdate = true ;
return tex;
}
KTX2 Compressed Textures GPU-compressed textures reduce VRAM and upload time. Requires a transcoder.
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js' ;
const ktx2Loader = new KTX2Loader ();
ktx2Loader.setTranscoderPath ('/libs/basis/' );
ktx2Loader.detectSupport (renderer);
ktx2Loader.load ('texture.ktx2' , texture => {
texture.colorSpace = THREE .SRGBColorSpace ;
material.map = texture;
material.needsUpdate = true ;
});
Prefer KTX2 for production — reduces VRAM by 4–8× vs PNG/JPG.
Texture Atlas Pack multiple textures into one to reduce draw calls.
const atlasTexture = loader.load ('atlas.png' );
atlasTexture.colorSpace = THREE .SRGBColorSpace ;
function setAtlasRegion (mesh, col, row, gridSize = 2 ) {
const uvScale = 1 / gridSize;
mesh.material .map .repeat .set (uvScale, uvScale);
mesh.material .map .offset .set (col * uvScale, row * uvScale);
}
setAtlasRegion (tree, 0 , 0 );
setAtlasRegion (rock, 1 , 0 );
setAtlasRegion (bush, 0 , 1 );
Memory Management
texture.dispose ();
function disposeMaterial (material ) {
const textureSlots = [
'map' , 'normalMap' , 'roughnessMap' , 'metalnessMap' ,
'aoMap' , 'emissiveMap' , 'displacementMap' , 'envMap' ,
'alphaMap' , 'lightMap' ,
];
textureSlots.forEach (slot => {
if (material[slot]) material[slot].dispose ();
});
material.dispose ();
}
console .log ('Textures in memory:' , renderer.info .memory .textures );
Performance Tips
Always set colorSpace — missing this causes incorrect colour rendering
Use KTX2/Basis compressed textures in production — 4–8× VRAM saving
Power-of-2 dimensions — non-POT textures cannot generate mipmaps and repeat poorly
Disable generateMipmaps for UI/video/canvas textures — they don't need it
Share textures between materials — same texture object = single GPU upload
Atlas small textures — fewer texture binds = fewer draw calls
Set anisotropy to renderer.capabilities.getMaxAnisotropy() for floor/terrain
const sharedTex = loader.load ('shared.jpg' );
const mat1 = new THREE .MeshStandardMaterial ({ map : sharedTex });
const mat2 = new THREE .MeshStandardMaterial ({ map : sharedTex });
See Also
threejs-materials — material types that use texture slots
threejs-lighting — HDR environment map loading
threejs-loaders — GLTFLoader, RGBELoader, KTX2Loader
three-js-best-practices — texture compression and VRAM budget