纹理贴图(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());常见坑(很“经典”)
- 贴图路径 404:Vite 开发时优先放
public/,用绝对路径/xxx.png - 贴图很糊:图片分辨率太低 / 斜视角没开 anisotropy / UV 不合理
- 贴图方向不对:有些资源需要
texture.flipY = false(尤其是 glTF 相关贴图)
练习
- 给一个
BoxGeometry加一张颜色贴图(map),并通过 GUI 控制repeat与rotation - 把
MeshBasicMaterial换成MeshStandardMaterial,加一盏DirectionalLight观察差异
