学习Three.js--材质(Material)
前置必读:材质通用规则 & 公共核心参数
一、通用规则
- 所有网格类材质 (
MeshXXXMaterial)都是THREE.Material的子类,共用一套核心公共参数,无需重复记忆; - 材质的参数均为配置对象({})传参 ,支持创建后通过
material.参数名 = 值动态修改; - 材质创建后可以复用给多个物体,能极大节省内存(比如100个立方体用同一个材质,只创建1个即可);
- 所有颜色值参数:支持16进制
0xffffff、RGB字符串#fff/rgb(255,255,255)、THREE.Color对象。
二、 所有材质【公共核心参数】
以下参数适用于 90% 的材质(MeshBasic/MeshLambert/MeshPhong/Standard/Physical 全部包含),一次记忆,全部受用!
javascript
{
color: 0xffffff, // 基础颜色,默认白色
transparent: false, // 是否开启透明效果,默认关闭 ❗开启透明必须设为true,opacity才生效
opacity: 1, // 透明度,取值范围 0(完全透明) ~ 1(完全不透明),默认1
visible: true, // 物体是否可见,true显示/false隐藏,默认true
side: THREE.FrontSide, // 渲染物体的哪个面,核心取值3种:
// THREE.FrontSide 只渲染正面(默认) | THREE.BackSide 只渲染背面 | THREE.DoubleSide 双面渲染
depthWrite: true, // 是否写入深度缓冲区,默认true;透明物体建议设为false,避免透明重叠闪烁
depthTest: true, // 是否开启深度测试,默认true;关闭后物体可能会穿透其他物体
wireframe: false, // 是否以线框模式渲染物体,默认false(实体),true则只显示几何体的边框线
wireframeLinewidth: 1, // 线框的线宽,默认1;❗注意:浏览器对WebGL的线宽支持有限,一般只能到1-2px
alphaTest: 0, // 透明度裁剪阈值,取值0~1;像素透明度低于该值则不渲染,解决透明边缘锯齿问题
map: null, // 颜色纹理贴图,传 THREE.Texture 纹理对象,用于给物体贴图片(比如木纹、皮肤)
}
一、网格基础材质 THREE.MeshBasicMaterial
核心特点
不受光照影响、无明暗变化,始终纯色/纹理显示,不需要添加光源就能渲染,性能最高
适用场景
调试几何体、UI元素、纯色简单物体、快速原型开发
完整调用语法
javascript
const material = new THREE.MeshBasicMaterial({
// 公共参数 + 自身专属参数(无专属,全是公共参数)
color: 0x00ff00,
transparent: false,
opacity: 1,
side: THREE.FrontSide,
wireframe: false,
map: null,
alphaTest: 0,
depthWrite: true
});
专属注意点
- 该材质无视所有光源 ,添加
AmbientLight/DirectionalLight等都不会有任何效果; wireframe: true时,能直观看到几何体的顶点和面结构,调试几何体形状的最佳材质。
二、网格漫反射材质 THREE.MeshLambertMaterial
核心特点
基于Lambert漫反射光照模型 ,对光源有响应、有明暗过渡,无高光效果,计算量低
适用场景
哑光粗糙表面(纸张、墙面、布料、水泥、木头、哑光塑料)
完整调用语法
javascript
const material = new THREE.MeshLambertMaterial({
// 公共参数(全部支持)
color: 0x00ff00,
transparent: false,
opacity: 1,
side: THREE.FrontSide,
wireframe: false,
map: null,
// 自身核心专属参数
emissive: 0x000000, // 自发光颜色,默认黑色(无自发光)
emissiveIntensity: 1, // 自发光强度,取值0~∞,默认1
emissiveMap: null, // 自发光纹理贴图,给物体贴发光纹理
vertexColors: false, // 是否使用顶点颜色,默认false
flatShading: false, // 是否使用平面着色,默认false(平滑着色)
});
所有参数详细释义(含公共+专属)
- 公共参数同上文,不再重复;
emissive:自发光色,不会照亮其他物体 ,只是让材质自身显示该颜色,比如设为0xff0000,物体会带红色发光效果;emissiveIntensity:调节自发光的亮度,值越大发光越明显;flatShading: true:几何体每个面会显示纯色,无平滑过渡,适合做低多边形风格;vertexColors: true:如果几何体设置了顶点颜色,材质会渲染顶点的颜色渐变。
注意点
- 必须添加光源,否则物体会显示纯黑色,完全不可见;
- 无高光参数,无法实现光泽效果,是哑光质感的最优选择。
三、网格高光材质 THREE.MeshPhongMaterial
核心特点
基于Phong高光光照模型 ,支持「漫反射+镜面高光」,对光源响应,有明显的高光光斑,计算量略高于MeshLambertMaterial
适用场景
有光泽的物体(漆面塑料、陶瓷、湿润的石头、抛光木头、电镀金属)
完整调用语法
javascript
const material = new THREE.MeshPhongMaterial({
// 公共参数(全部支持)
color: 0x00ff00,
transparent: false,
opacity: 1,
side: THREE.FrontSide,
wireframe: false,
map: null,
// 继承MeshLambert的自发光参数
emissive: 0x000000,
emissiveIntensity: 1,
emissiveMap: null,
flatShading: false,
// 自身核心高光专属参数(重中之重)
specular: 0x111111, // 高光颜色,默认浅灰色
shininess: 30, // 高光的「亮度+范围」,取值0~1000+,默认30
});
高光核心参数释义
specular:决定高光光斑的颜色 ,比如:- 塑料材质:设为
0xffffff(白色高光),最真实; - 金属材质:设为和
color相同的颜色,高光和本体同色;
- 塑料材质:设为
shininess:核心高光参数,值越小 → 高光范围越大、亮度越低 ;值越大 → 高光范围越小、亮度越高 。- 示例:
shininess:5→ 大面积柔和高光;shininess:100→ 小面积刺眼高光。
- 示例:
注意点
- 同样必须添加光源,无光源则全黑;
- Phong的高光效果是模拟的光泽,不是物理真实的,高光光斑略显生硬,但性能不错,适合简单光泽场景;
- 该材质的高光计算在顶点上,低面数几何体的高光会有锯齿。
四、物理基础材质 THREE.MeshStandardMaterial 【默认首选】
核心特点
基于 PBR(Physically Based Rendering)物理渲染 ,完全遵循真实世界的光照规律,参数少但效果极致真实,计算量适中,Three.js官方推荐的默认首选材质,也是目前最常用的材质!
适用场景
99%的现代3D场景:游戏、产品展示、建筑可视化、电商3D商品、写实模型,能替代所有传统材质(Lambert/Phong)
核心优势
- 传统材质(Phong/Lambert)是「模拟光照」,PBR是「物理光照」,效果真实度天差地别;
- 参数语义化,无需调复杂的高光/漫反射,通过「粗糙度+金属度」就能实现所有质感。
完整调用语法
javascript
const material = new THREE.MeshStandardMaterial({
// 公共参数(全部支持)
color: 0x00ff00,
transparent: false,
opacity: 1,
side: THREE.FrontSide,
wireframe: false,
map: null,
alphaTest: 0,
depthWrite: true,
// PBR 核心四大基础参数 (必学!!)
roughness: 0.5, // 粗糙度,取值 0(镜面光滑) ~ 1(完全粗糙),默认0.5
metalness: 0.5, // 金属度,取值 0(非金属) ~ 1(纯金属),默认0.5
emissive: 0x000000,// 自发光颜色,默认黑色,无自发光
emissiveIntensity:1,// 自发光强度,默认1
// PBR 进阶纹理贴图(提升真实度)
roughnessMap: null, // 粗糙度纹理,让物体表面粗糙度有细节变化
metalnessMap: null, // 金属度纹理,让物体部分区域是金属、部分是非金属
normalMap: null, // 法线贴图,模拟物体表面凹凸细节(无需修改几何体)
aoMap: null, // 环境遮蔽贴图,模拟物体缝隙/凹陷处的阴影,提升层次感
displacementMap: null, // 置换贴图,真正修改几何体顶点,实现凹凸效果
// 特殊物理参数
clearcoat: 0, // 清漆层,取值0~1,默认0;模拟车漆/指甲油的表层光泽
clearcoatRoughness:0,// 清漆层粗糙度,取值0~1,默认0
transmission: 0, // 透射率,取值0~1,默认0;模拟玻璃/半透明物体的透光效果
});
PBR 核心参数【必懂必记】(4个)
这是该材质的灵魂,记住取值范围+含义,就能调出所有质感,无任何例外!
roughness(粗糙度) 0~10→ 镜面级光滑,反射所有光线,高光极强(比如镜子、抛光金属);1→ 完全粗糙,无任何高光,纯哑光(比如纸张、水泥);- 中间值 → 半光泽(比如塑料、漆面、木头)。
metalness(金属度) 0~10→ 非金属材质(塑料、玻璃、石头、布料),反射环境光,高光颜色固定;1→ 纯金属材质(金、银、铜),反射自身颜色,高光和本体同色;- 中间值 → 合金材质(比如不锈钢、黄铜)。
emissive+emissiveIntensity:自发光,不会照亮其他物体,比如霓虹灯、指示灯、发光logo。- 颜色
color:金属度0时是「物体本身颜色」;金属度1时,color决定金属的颜色(比如金色0xffd700、银色0xcccccc)。
质感调试万能公式
- 哑光塑料 →
roughness:0.8, metalness:0 - 镜面塑料 →
roughness:0.1, metalness:0 - 不锈钢 →
roughness:0.2, metalness:1, color:0xcccccc - 黄金 →
roughness:0.1, metalness:1, color:0xffd700 - 木头 →
roughness:0.7, metalness:0, color:0x8b4513 - 玻璃 →
roughness:0, metalness:0, transmission:0.9
五、高级物理材质 THREE.MeshPhysicalMaterial
核心特点
MeshStandardMaterial 的超集 ,完全兼容其所有参数+方法,在其基础上增加了更精细的物理光学参数,实现极致写实的物理效果,PBR天花板材质!
适用场景
超写实3D场景:汽车车漆、玻璃/水晶、宝石、珍珠、丝绸、拉丝金属、多层镀膜材质
完整调用语法
javascript
const material = new THREE.MeshPhysicalMaterial({
// 完全包含 MeshStandardMaterial 的 所有参数(无需重复写)
color: 0x00ff00,
roughness: 0.5,
metalness: 0.5,
emissive: 0x000000,
clearcoat:0,
transmission:0,
// 新增的【专属高级参数】(核心!)
clearcoatRoughness: 0, // 清漆层粗糙度,0=镜面清漆,1=哑光清漆
sheen: 0, // 光泽层,0~1,默认0;模拟丝绸、天鹅绒、布料的柔和高光
sheenRoughness: 0.5, // 光泽层粗糙度,0~1,默认0.5
sheenColor: 0xffffff, // 光泽层颜色,默认白色
iridescence: 0, // 虹彩/色散,0~1,默认0;模拟珍珠、肥皂泡、CD光盘的彩虹反光
iridescenceIOR: 1.5, // 虹彩折射率,默认1.5
iridescenceThicknessRange: [100, 400], // 虹彩厚度范围,控制彩虹颜色
anisotropy: 0, // 各向异性,-1~1,默认0;模拟拉丝金属、头发的方向性高光
thickness: 0.1, // 厚度,0~∞,默认0.1;配合transmission使用,模拟玻璃的厚度(厚玻璃颜色更深)
reflectivity: 1, // 折射率,1~2.333,默认1;控制玻璃/水的折射效果
});
专属参数核心释义
sheen:丝绸/天鹅绒的核心参数,能实现「反向高光」,布料的质感全靠它;iridescence:彩虹色散,珍珠、肥皂泡、车漆的金属珠光效果,必调参数;anisotropy:拉丝金属的核心,比如不锈钢拉丝面板、头发,高光会沿着拉丝方向延伸;thickness:玻璃厚度,比如厚玻璃杯的边缘会偏绿,薄玻璃则透明,真实度拉满。
注意点
- 该材质计算量比
MeshStandardMaterial略高,但现代浏览器/显卡完全能承载; - 能用
MeshStandardMaterial实现的效果,就用它;需要极致细节时,再用MeshPhysicalMaterial。
六、点材质 THREE.PointsMaterial
核心特点
专门用于 THREE.Points(粒子系统),只能渲染点/粒子,不能渲染网格几何体
适用场景
粒子特效:星空、烟雾、雨滴、雪花、灰尘、点云模型、星空背景
完整调用语法
javascript
const material = new THREE.PointsMaterial({
color: 0xffffff, // 粒子颜色,默认白色
size: 1, // 粒子大小(像素),默认1
sizeAttenuation: true, // 是否开启「近大远小」,默认true;false则所有粒子大小一致
transparent: true, // 是否透明,默认false(粒子特效必开)
opacity: 1, // 透明度,0~1,默认1
map: null, // 粒子纹理贴图,比如用圆形贴图做圆点粒子,用雪花贴图做雪花
alphaTest: 0.1, // 透明裁剪,解决粒子边缘锯齿,建议设0.1
depthWrite: false, // 关闭深度写入,解决透明粒子重叠时的闪烁问题(必开)
blending: THREE.AdditiveBlending, // 混合模式,AdditiveBlending=叠加,粒子更亮(适合火焰/星光)
emissive: 0xffffff, // 自发光颜色,默认白色
emissiveIntensity:1, // 自发光强度
});
// 配套使用:创建粒子系统
const geometry = new THREE.BufferGeometry().setFromPoints( pointsArr ); // 点数组
const points = new THREE.Points( geometry, material );
scene.add(points);
核心参数
size:粒子的像素大小,值越大粒子越大;sizeAttenuation: true:粒子会像真实物体一样,离相机越近越大,越远越小,必开;depthWrite: false:透明粒子的必备参数,否则粒子重叠时会出现穿透/闪烁的问题。
七、线材质 「LineBasicMaterial + LineDashedMaterial」
通用特点
专门用于 THREE.Line / THREE.LineSegments(线段/线条几何体),只能渲染线条,不能渲染网格
适用场景
绘制辅助线、坐标轴、边框、电路图、激光线、轨迹线等
7.1 实线材质 THREE.LineBasicMaterial
javascript
const material = new THREE.LineBasicMaterial({
color: 0xffffff, // 线条颜色,默认白色
linewidth: 1, // 线宽(像素),默认1;❗浏览器限制,一般最大只能到2px
transparent: false, // 是否透明
opacity: 1, // 透明度
dashed: false, // 是否虚线,默认false(实线)
});
7.2 虚线材质 THREE.LineDashedMaterial【高频使用】
javascript
const material = new THREE.LineDashedMaterial({
color: 0xffffff, // 线条颜色
linewidth: 1, // 线宽
transparent: false,
opacity: 1,
dashSize: 3, // 【核心】虚线的「实线部分长度」,默认3
gapSize: 1, // 【核心】虚线的「空白部分长度」,默认1
scale: 1, // 缩放比例,默认1;整体缩放dashSize和gapSize
});
// ❗ 必加:给线段几何体调用 computeLineDistances(),否则虚线不生效!
const lineGeometry = new THREE.BufferGeometry().setFromPoints( pointsArr );
lineGeometry.computeLineDistances();
const line = new THREE.Line( lineGeometry, material );
scene.add(line);
注意点
- 虚线材质必须调用
geometry.computeLineDistances(),否则会显示为实线,无虚线效果; linewidth受WebGL限制,无法设置超大线宽,如需粗线条,建议用网格几何体模拟。
八、精灵材质 THREE.SpriteMaterial
核心特点
专门用于 THREE.Sprite(精灵/广告牌),本质是始终朝向相机的2D平面,不会随视角旋转,永远正面朝向屏幕
适用场景
3D场景中的2D元素:图标、血条、标签、子弹、火焰粒子、雪花粒子、2D精灵特效
完整调用语法
javascript
const material = new THREE.SpriteMaterial({
color: 0xffffff, // 精灵颜色
map: null, // 精灵纹理贴图(核心,一般都用贴图,比如图标图片)
transparent: true, // 是否透明,默认false(必开,否则背景是白色)
opacity: 1, // 透明度
rotation: 0, // 精灵旋转角度(弧度制),默认0;绕中心旋转
center: new THREE.Vector2(0.5,0.5), // 旋转中心,默认中心(0.5,0.5)
sizeAttenuation: true, // 是否近大远小,默认true;false则精灵大小固定
depthWrite: false, // 关闭深度写入,解决精灵遮挡问题
});
// 配套使用
const sprite = new THREE.Sprite( material );
sprite.scale.set(1,1,1); // 设置精灵大小
scene.add(sprite);
注意点
- 精灵是2D平面 ,没有厚度,所以
side参数无效; - 精灵的大小通过
sprite.scale控制,不是材质参数。
九、阴影材质 THREE.ShadowMaterial
核心特点
官方正确特性:材质自身完全透明,不接收任何光照,只显示「其他物体投射过来的阴影」
适用场景
地面/平面作为阴影接收器,比如创建一个透明的地面,只显示3D物体的阴影,不显示地面本身,让物体看起来像悬浮在空中,是实现真实阴影的最优方案!
完整调用语法
javascript
const material = new THREE.ShadowMaterial({
opacity: 0.5, // 【唯一核心参数】阴影的透明度,取值0~1,默认0.5
// 无其他专属参数,公共参数仅支持 transparent/depthWrite
transparent: true, // 固定为true,无需修改
depthWrite: false, // 建议关闭,避免阴影闪烁
});
使用注意点
-
必须开启光源的阴影投射 + 物体的阴影投射 + 地面的阴影接收 :
javascriptdirectionalLight.castShadow = true; // 光源投射阴影 cube.castShadow = true; // 物体投射阴影 ground.receiveShadow = true; // 地面接收阴影 -
opacity越小,阴影越淡;越大,阴影越深。
十、自定义着色器材质 THREE.ShaderMaterial
核心特点
完全自定义顶点着色器(VertexShader) 和片元着色器(FragmentShader) ,使用GLSL语言编写,能实现 任何Three.js内置材质做不到的视觉效果,是Three.js的高级核心功能
适用场景
水体、火焰、溶解效果、扭曲变形、玻璃折射、扫描线、像素化、后处理特效等自定义视觉效果
完整调用语法
javascript
const material = new THREE.ShaderMaterial({
// 核心:自定义GLSL着色器代码
vertexShader: `
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
attribute vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`, // 顶点着色器:控制物体的顶点位置/变形
fragmentShader: `
uniform vec3 uColor;
void main() {
gl_FragColor = vec4(uColor, 1.0);
}
`, // 片元着色器:控制物体的像素颜色/纹理/特效
// 自定义全局变量(JS传递数据到GLSL,核心!)
uniforms: {
uColor: { value: new THREE.Color(0x00ff00) }, // 颜色变量
uTime: { value: 0 }, // 时间变量,用于做动画
uTexture: { value: texture }, // 纹理变量
},
// 公共材质参数(全部支持)
transparent: true,
opacity: 1,
side: THREE.DoubleSide,
depthWrite: false,
wireframe: false,
});
核心参数释义
vertexShader:顶点着色器,运行在GPU上,控制每个顶点的位置、法线、纹理坐标等;fragmentShader:片元着色器,运行在GPU上,控制每个像素的最终颜色,所有视觉特效都在这里实现;uniforms:JS和GLSL之间的数据桥梁 ,可以在JS中动态修改uniforms.uTime.value,GLSL中就能实时获取,实现动画。
注意点
- Three.js会自动注入内置变量 (比如
projectionMatrix、modelViewMatrix),无需手动声明; - GLSL语言和JS语法不同,需要单独学习基础,入门简单。
十一、原生着色器材质 THREE.RawShaderMaterial
核心特点
和 THREE.ShaderMaterial 几乎完全一致,唯一的区别是:不会自动注入Three.js的任何内置变量
适用场景
高级自定义着色器,需要完全掌控GLSL代码的所有变量,比如移植外部WebGL着色器、编写极致优化的着色器、实现底层图形学效果
调用语法
javascript
const material = new THREE.RawShaderMaterial({
vertexShader: `
// ❗ 必须手动声明所有变量,Three.js不自动注入
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
attribute vec3 position;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec3 uColor;
void main() {
gl_FragColor = vec4(uColor, 1.0);
}
`,
uniforms: { uColor: { value: new THREE.Color(0x00ff00) } },
transparent: true,
});
核心区别(和ShaderMaterial)
ShaderMaterial:自动注入内置变量,开发效率高,适合绝大多数自定义场景;
RawShaderMaterial:无自动注入,完全手动,灵活性最高,适合高级底层开发。
材质学习总结 & 优先级建议(必看)
1. 材质使用优先级(按推荐度排序)
- 优先用
MeshStandardMaterial→ 99%场景够用,物理真实、参数简单、性能均衡; - 需要极致细节 → 用
MeshPhysicalMaterial; - 调试几何体 → 用
MeshBasicMaterial; - 简单哑光物体+低性能设备 → 用
MeshLambertMaterial; - 简单光泽物体 → 用
MeshPhongMaterial; - 粒子/点云 → 用
PointsMaterial; - 线条 → 用
LineBasicMaterial/LineDashedMaterial; - 2D精灵/图标 → 用
SpriteMaterial; - 透明地面+阴影 → 用
ShadowMaterial; - 自定义特效 → 用
ShaderMaterial/RawShaderMaterial。
2. 核心记忆点
- 所有网格材质共用一套公共参数,无需重复记忆;
- PBR材质的核心是「粗糙度+金属度」,记住0~1的取值规则,就能调出所有质感;
- 材质可以复用,多个物体用同一个材质能极大优化性能;
- 透明材质建议开启
transparent:true+depthWrite:false,避免闪烁/穿透问题。