关于 threejs-syntax-materials
面向 Three.js 开发者的材质与纹理参考技能,涵盖材质选择、配置及常见问题。内容包括颜色空间规则、生命周期方法和渲染注意事项。
主要功能
- 01按渲染用途选择材质
- 02常用材质属性与方法
- 03PBR 与高级材质说明
- 04纹理颜色空间与环绕规则
- 05着色器更新和 GPU 清理建议
适用场景
- 01为场景对象选择材质
- 02正确设置纹理颜色空间
- 03移除对象时避免 GPU 泄漏
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ impertio-studio/ three.js-claude-skill-package --skill threejs-syntax-materials安装后在 Claude Code 中输入/threejs-syntax-materials确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitkeepreferences/anti-patterns.mdexamples.mdmethods.md详细介绍
threejs-syntax-materials
快速参考
材质类型决策树
| 使用场景 | 材质 | 原因 |
|---|---|---|
| UI 元素、无光照场景 | MeshBasicMaterial | 开销最低,无需计算光照 |
| 哑光漫反射(低端设备) | MeshLambertMaterial | 漫反射计算快速,无高光 |
| 传统镜面高光 | MeshPhongMaterial | Blinn-Phong 模型,不符合物理规律 |
| 通用 3D(推荐) | MeshStandardMaterial | 基于 PBR 的金属度/粗糙度模型,行业标准 |
| 玻璃、汽车漆、织物、肥皂泡 | MeshPhysicalMaterial | 高级 PBR(清漆层、透射、光泽、虹彩) |
| 卡通/动漫风格 | MeshToonMaterial | 离散的卡通着色阶 |
| 雕刻预览、无光照 | MeshMatcapMaterial | Matcap 纹理,无需设置光照 |
| 调试法线 | MeshNormalMaterial | RGB = 表面法线方向 |
| 隐形阴影接收面 | ShadowMaterial | 透明阴影接收材质 |
| 实线 | LineBasicMaterial | 简单的彩色线条 |
| 虚线 | LineDashedMaterial | 需要调用 line.computeLineDistances() |
| 粒子 | PointsMaterial | 点云渲染 |
| 广告牌 | SpriteMaterial | 四边形始终朝向摄像机 |
基础材质属性(所有材质)
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
side | number | FrontSide | FrontSide、BackSide 或 DoubleSide |
transparent | boolean | false | 启用 Alpha 混合 |
opacity | number | 1 | 低于 1 时,必须设置 transparent: true 才会生效 |
depthWrite | boolean | true | 写入深度缓冲区 |
depthTest | boolean | true | 与深度缓冲区进行测试 |
blending | number | NormalBlending | NoBlending、AdditiveBlending、SubtractiveBlending、MultiplyBlending、CustomBlending |
alphaTest | number | 0 | 丢弃 Alpha 值低于此值的片段 |
visible | boolean | true | 是否渲染此材质 |
wireframe | boolean | false | 线框渲染模式 |
fog | boolean | true | 受场景雾效影响 |
clippingPlanes | Plane[] | null | 裁剪平面数组 |
clipIntersection | boolean | false | 在所有平面的交集处裁剪(而非并集) |
needsUpdate | boolean | false | 设置为 true 以触发着色器重新编译 |
toneMapped | boolean | true | 应用渲染器色调映射 |
基础材质方法
| 方法 | 签名 | 说明 |
|---|---|---|
clone | (): Material | 克隆材质 |
copy | (source: Material): Material | 从源对象复制属性 |
dispose | (): void | 释放 GPU 资源——移除时务必调用 |
onBeforeCompile | (shader, renderer): void | 在编译前修改着色器的钩子 |
setValues | (values: Object): void | 一次设置多个属性 |
重要警告
绝不要在未设置 transparent: true 的情况下设置 opacity < 1——不透明度值会被静默忽略。务必同时设置两者。
绝不要在 MeshStandardMaterial 已足够时使用 MeshPhysicalMaterial——Physical 会编译出明显更大的着色器。只有在需要清漆、透射、光泽、虹彩或各向异性时才使用它。
绝不要在法线贴图、粗糙度贴图、金属度贴图或任何数据纹理上设置 SRGBColorSpace——这会破坏数据并导致光照不正确。只有在漫反射/颜色/自发光纹理上设置 SRGBColorSpace。
绝不要在移除对象时忘记调用 material.dispose() 和 texture.dispose()——GPU 内存泄漏会不断累积,最终导致应用崩溃。
绝不要在 LineBasicMaterial 上设置 linewidth > 1——由于 WebGL 的限制,大多数平台会静默忽略此设置。对于粗线,务必使用 three/addons/lines/ 中的 Line2 + LineMaterial。
务必在更改会影响着色器编译的属性后设置 material.needsUpdate = true(例如,切换 flatShading、更改 side、在运行时添加/移除纹理贴图)。
务必在使用非 (1, 1) 的 texture.repeat 值时,将 wrapS 和 wrapT 设置为 RepeatWrapping——默认的 ClampToEdgeWrapping 不会平铺纹理。
MeshStandardMaterial(PBR)
适用于大多数 3D 场景的推荐材质。采用基于物理的金属度/粗糙度工作流。
import { MeshStandardMaterial, TextureLoader, SRGBColorSpace, RepeatWrapping } from 'three';
const loader = new TextureLoader();
const material = new MeshStandardMaterial({
color: 0xffffff,
roughness: 0.7, // 0 = mirror, 1 = fully rough
metalness: 0.0, // 0 = dielectric, 1 = metal
map: null, // Diffuse/albedo texture
roughnessMap: null, // Per-pixel roughness
metalnessMap: null, // Per-pixel metalness
normalMap: null, // Surface normal perturbation
normalScale: new Vector2(1, 1),
aoMap: null, // Ambient occlusion (requires uv2)
aoMapIntensity: 1.0,
emissive: 0x000000, // Emissive color
emissiveMap: null, // Emissive texture
emissiveIntensity: 1.0,
envMap: null, // Environment reflection map
envMapIntensity: 1.0,
bumpMap: null, // Grayscale height map
bumpScale: 1.0,
displacementMap: null, // Vertex displacement map
displacementScale: 1.0,
displacementBias: 0.0,
alphaMap: null, // Per-pixel transparency
lightMap: null, // Baked lighting (requires uv2)
lightMapIntensity: 1.0,
flatShading: false,
wireframe: false,
fog: true
});
MeshPhysicalMaterial(高级 PBR)
在 MeshStandardMaterial 的所有属性基础上扩展了以下属性:
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
clearcoat | float | 0.0 | 清漆层强度(0-1) |
clearcoatRoughness | float | 0.0 | 清漆粗糙度 |
clearcoatMap | Texture | null | 清漆强度贴图 |
clearcoatNormalMap | Texture | null | 清漆法线贴图 |
transmission | float | 0.0 | 基于物理的透明度(0-1) |
transmissionMap | Texture | null | 透射贴图 |
thickness | float | 0.0 | 透射体积厚度 |
thicknessMap | Texture | null | 厚度贴图 |
ior | float | 1.5 | 折射率(1.0-2.333) |
attenuationDistance | float | Infinity | 光在体积中的衰减距离 |
attenuationColor | Color | white | 光衰减色调 |
sheen | float | 0.0 | 光泽层强度(类似织物) |
sheenColor | Color | 0x000000 | 光泽色调 |
sheenRoughness | float | 1.0 | 光泽粗糙度 |
iridescence | float | 0.0 | 薄膜干涉(0-1) |
iridescenceIOR | float | 1.3 | 虹彩折射率 |
iridescenceThicknessRange | [float, float] | [100, 400] | 薄膜厚度范围(nm) |
anisotropy | float | 0.0 | 各向异性反射强度 |
anisotropyRotation | float | 0.0 | 各向异性旋转(弧度) |
specularIntensity | float | 1.0 | 镜面层强度 |
specularColor | Color | white | 镜面色调 |
dispersion | float | 0.0 | 色散(彩虹效果) |
reflectivity | float | 0.5 | 法线入射时的反射率 |
纹理系统
颜色空间规则(重要)
| 地图类型 | 颜色空间 | 使用的通道 |
|---|---|---|
map(漫反射/反照率) | SRGBColorSpace | RGB(A) |
emissiveMap | SRGBColorSpace | RGB |
lightMap | SRGBColorSpace | RGB |
envMap | SRGBColorSpace | RGB |
sheenColorMap | SRGBColorSpace | RGB |
specularColorMap | SRGBColorSpace | RGB |
normalMap | NoColorSpace | RGB |
roughnessMap | NoColorSpace | G 通道 |
metalnessMap | NoColorSpace | B 通道 |
aoMap | NoColorSpace | R 通道 |
bumpMap | NoColorSpace | R 通道 |
displacementMap | NoColorSpace | R 通道 |
alphaMap | NoColorSpace | R 通道 |
clearcoatMap | NoColorSpace | R 通道 |
clearcoatRoughnessMap | NoColorSpace | R 通道 |
clearcoatNormalMap | NoColorSpace | RGB |
transmissionMap | NoColorSpace | R 通道 |
thicknessMap | NoColorSpace | R 通道 |
iridescenceMap | NoColorSpace | R 通道 |
iridescenceThicknessMap | NoColorSpace | R 通道 |
sheenRoughnessMap | NoColorSpace | R 通道 |
anisotropyMap | NoColorSpace | RG 通道 |
specularIntensityMap | NoColorSpace | A 通道 |
规则:漫反射/自发光/颜色纹理 = SRGBColorSpace。所有数据纹理 = NoColorSpace。设置错误会导致渲染效果褪色或过度饱和。
纹理加载器
| 加载器 | 格式 | 导入 |
|---|---|---|
TextureLoader | PNG、JPG、WebP | three 核心 |
CubeTextureLoader | 6 张 PNG/JPG 立方体贴图 | three 核心 |
RGBELoader | .hdr(Radiance HDR) | three/addons/loaders/RGBELoader.js |
EXRLoader | .exr(OpenEXR HDR) | three/addons/loaders/EXRLoader.js |
KTX2Loader | .ktx2(GPU 压缩) | three/addons/loaders/KTX2Loader.js |
环绕模式
| 常量 | 描述 |
|---|---|
ClampToEdgeWrapping | 拉伸边缘纹素(默认) |
RepeatWrapping | 平铺/重复纹理 |
MirroredRepeatWrapping | 交替镜像平铺 |
过滤模式
| 常量 | 类型 | 描述 |
|---|---|---|
NearestFilter | 放大/缩小 | 像素化、清晰(复古风格、卡通渐变) |
LinearFilter | 放大/缩小 | 平滑插值 |
LinearMipmapLinearFilter | 缩小 | 三线性过滤(默认,质量最佳) |
纹理属性
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
wrapS / wrapT | number | ClampToEdgeWrapping | 环绕模式 |
magFilter | number | LinearFilter | 放大过滤器 |
minFilter | number | LinearMipmapLinearFilter | 缩小过滤器 |
anisotropy | number | 1 | 各向异性过滤(最大值 = renderer.capabilities.getMaxAnisotropy()) |
repeat | Vector2 | (1, 1) | UV 重复次数 |
offset | Vector2 | (0, 0) | UV 偏移 |
rotation | number | 0 | UV 旋转角度(弧度) |
center | Vector2 | (0, 0) | 旋转中心 |
flipY | boolean | true | 上传时垂直翻转 |
colorSpace | string | NoColorSpace | 颜色空间解释方式 |
generateMipmaps | boolean | true | 自动生成 mipmap |
needsUpdate | boolean | false | 触发 GPU 重新上传 |
flipY 规则
flipY = true(默认):适用于已加载的图像纹理(PNG、JPG)flipY = false:对于WebGLRenderTarget纹理、DataTexture和帧缓冲区纹理,始终使用此设置
材质释放
// ALWAYS dispose materials and textures when removing objects
function disposeMesh(mesh) {
if (mesh.material) {
// Dispose all texture maps
for (const key of Object.keys(mesh.material)) {
const value = mesh.material[key];
if (value && value.isTexture) {
value.dispose();
}
}
mesh.material.dispose();
}
if (mesh.geometry) {
mesh.geometry.dispose();
}
}
needsUpdate 标记
运行时更改以下属性后,始终设置 material.needsUpdate = true:
- 切换
flatShading - 更改
side(FrontSide/BackSide/DoubleSide) - 添加或移除纹理贴图(例如,将
map从null设置为纹理) - 更改
transparent或alphaTest - 切换
wireframe - 任何会改变已编译着色器变体的属性
切勿每帧都设置 needsUpdate = true——这会触发开销巨大的着色器重新编译。仅在属性更改后设置一次。
对于纹理:修改 texture.image 数据后,设置 texture.needsUpdate = true,以触发 GPU 重新上传。
卡通材质特别规则
使用 MeshToonMaterial 时,始终将 gradientMap.minFilter = NearestFilter 和 gradientMap.magFilter = NearestFilter。线性过滤会将离散的明暗阶梯模糊为平滑渐变,破坏卡通效果。
参考链接
- references/methods.md —— 所有材质类型及其构造函数签名和关键属性
- references/examples.md —— 完整可运行的示例(PBR、纹理、多材质)
- references/anti-patterns.md —— 不要采用的做法及其说明