Skip to content

纹理贴图(Texture):把“颜色”升级成“表面”

在 Three.js 里,**贴图(Texture)**本质是 GPU 可采样的一张图片(2D 数据)。材质把它当作输入:用贴图的颜色/法线/粗糙度等信息,计算最终的像素结果。

什么时候需要贴图

  • 物体表面有复杂细节:木纹、划痕、文字、图案
  • 需要更真实的光照反应:粗糙度/金属度变化、法线细节
  • 需要“图像驱动”的效果:遮罩、渐变、噪声

最常用:TextureLoader 加载图片

ts
import * as THREE from "three";

const textureLoader = new THREE.TextureLoader();
const albedo = textureLoader.load("/textures/wood/color.jpg");

const material = new THREE.MeshStandardMaterial({
  map: albedo,
});

贴图通常放在 public/ 下,通过 URL 访问(例如 /textures/...)。

关键概念 1:颜色空间(sRGB vs Linear)

很多“颜色贴图”(Albedo/BaseColor)来自图片编辑软件,它们通常是 sRGB。如果颜色空间设置不对,常见现象是“发灰/偏暗/对比不对”。

  • 颜色贴图:通常需要 sRGB
  • 数据贴图(normal/roughness/metalness/ao/height 等):应保持线性(Linear)

在较新的 Three.js 版本中,推荐写法类似:

ts
albedo.colorSpace = THREE.SRGBColorSpace;

关键概念 2:Wrap / Repeat(平铺)

ts
albedo.wrapS = THREE.RepeatWrapping;
albedo.wrapT = THREE.RepeatWrapping;
albedo.repeat.set(4, 4);

如果你设置了 RepeatWrapping,但没有生效,通常是忘了设置 wrapS/wrapT

关键概念 3:过滤、MipMap 与清晰度

  • MinFilter/MagFilter 决定缩放时怎么采样
  • MipMap 会生成多级纹理,减少远处闪烁(代价是额外显存)
  • **Anisotropy(各向异性)**能提升斜视角地面的清晰度(很实用)
ts
albedo.anisotropy = Math.min(8, renderer.capabilities.getMaxAnisotropy());

常见坑(很“经典”)

  1. 贴图路径 404:Vite 开发时优先放 public/,用绝对路径 /xxx.png
  2. 贴图很糊:图片分辨率太低 / 斜视角没开 anisotropy / UV 不合理
  3. 贴图方向不对:有些资源需要 texture.flipY = false(尤其是 glTF 相关贴图)

练习

  • 给一个 BoxGeometry 加一张颜色贴图(map),并通过 GUI 控制 repeatrotation
  • MeshBasicMaterial 换成 MeshStandardMaterial,加一盏 DirectionalLight 观察差异