Skills Agentes

Threejs Textures

Texturas en Three.js: tipos de textura, mapeo UV, mapas de entorno y ajustes. Úsalo al trabajar con imágenes, coordenadas UV, cubemaps, entornos HDR u optimización de texturas.

Estrellas
49.5k

en todo el repo

Actividad
36

0–100, la ruta de este skill

Actualizado
hace 4 meses

último commit aquí

Commits
0

últimos 90 días

Contexto
3.4k tok

45 tok en reposo

Paquete
1 archivo

13 KB

Instalar

Funciona con cualquier agente que lea SKILL.md

npx -y skills add calesthio/OpenMontage --skill threejs-textures --agent claude-code

Se instala solo en este repositorio.

Qué hace

  • Cubre la carga y configuración de texturas en Three.js, y los distintos tipos de textura
  • Trata cube textures, texturas HDR, render targets y `CubeCamera`
  • Explica el mapeo UV y los atlas de textura
  • Repasa los mapas de textura de material y las texturas procedurales
  • Documenta la gestión de memoria de texturas y consejos de rendimiento

Úsalo cuando

  • Trabajar con imágenes como textura
  • Manejar coordenadas UV
  • Usar cubemaps o entornos HDR
  • Optimizar el uso de texturas

No lo uses cuando

    Qué lo activa

    Di cualquiera de estas frases y el agente debería cargar este skill.

    • Aplica esta textura al objeto
    • Monta un cubemap de entorno
    • Ajusta las coordenadas UV de esta malla
    • Las texturas ocupan mucha memoria, ¿cómo lo optimizo?

    SKILL.md

    En inglés

    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

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

    Reproducido de calesthio/OpenMontage bajo licencia AGPL-3.0. Leer esta página en markdown.

    Archivos

    1 archivo en el paquete. Solo se lee SKILL.md al activarse — las referencias se cargan si el skill decide que las necesita.

    Detalles

    Creador
    calesthio
    Categoría
    Diseño y UI
    Licencia
    AGPL-3.0
    Recursos incluidos
    Solo SKILL.md
    Código fuente
    Ver SKILL.md

    Etiquetas

    Más de calesthio/OpenMontage

    Este repo incluye 89 skills. Si instalas uno, normalmente ya tienes los demás.

    Comfyui

    49.5k

    Úsalo al trabajar con workflows de ComfyUI en OpenMontage: comfyui_image/video/music, workflows propios, selección de output_node, modelos que faltan, LoRAs, poca VRAM e importación de workflows de la comunidad.

    Costo de contexto al activarse
    1.9k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 9 días
    diseno ui

    Genera vídeo cinematográfico de 4-30 s con ByteDance Seedance 2.5 por fal.ai, Volcengine Ark, Runway o ComfyUI. Cubre el contrato de prompt 2.5, cortes duros, locks de continuidad y voz.

    Costo de contexto al activarse
    3.2k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 4 días
    diseno ui

    Genera narración expresiva y multilingüe con fish.audio (modelos S1 / S2) y reutiliza voces clonadas mediante reference_id.

    Costo de contexto al activarse
    1.4k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 9 días
    diseno ui

    Genera y edita conversacionalmente vídeos cortos con Google Gemini Omni Flash: itera con ediciones en lenguaje natural, clips de 3-10s a 720p con audio y texto en pantalla, e imágenes de referencia por etiquetas.

    Costo de contexto al activarse
    2.1k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 9 días
    Permisos
    diseno ui

    Genera vídeo con MiniMax H3 (Hailuo 3.0) por la API oficial v2, fal.ai, Runway, nodos partner de ComfyUI o pesos abiertos locales. Clips de 4-15s a 2K con animación de primer/último fotograma.

    Costo de contexto al activarse
    582 tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 9 días
    diseno ui

    Genera, reconstruye, inspecciona y enruta activos 3D de producción para mundos de OpenMontage con Atlas Cloud, fal.ai, catálogos con licencia y Blender.

    Costo de contexto al activarse
    1.2k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 9 días
    diseno ui

    Skills relacionados

    Genera, reconstruye, inspecciona y enruta activos 3D de producción para mundos de OpenMontage con Atlas Cloud, fal.ai, catálogos con licencia y Blender.

    Costo de contexto al activarse
    1.2k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 9 días
    diseno ui

    Acestep

    49.5k

    Generación musical con ACE-Step 1.5: música de fondo, pistas con voz, versiones y extracción de stems para producción de vídeo.

    Costo de contexto al activarse
    2.3k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 4 meses
    diseno ui

    Genera vídeos con IA desde texto usando varias pasarelas — HeyGen, fal.ai, Kling y Gemini — con soporte de imagen a vídeo y comparación entre VEO, Kling, Sora, Runway, Seedance y MiniMax.

    Costo de contexto al activarse
    3k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    el mes pasado
    diseno ui