学习Three.js–材质(Material)

学习Three.js--材质(Material)

前置必读:材质通用规则 & 公共核心参数

一、通用规则

  1. 所有网格类材质MeshXXXMaterial)都是 THREE.Material 的子类,共用一套核心公共参数,无需重复记忆;
  2. 材质的参数均为配置对象({})传参 ,支持创建后通过 material.参数名 = 值 动态修改;
  3. 材质创建后可以复用给多个物体,能极大节省内存(比如100个立方体用同一个材质,只创建1个即可);
  4. 所有颜色值参数:支持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(平滑着色)
});

所有参数详细释义(含公共+专属)

  1. 公共参数同上文,不再重复;
  2. emissive:自发光色,不会照亮其他物体 ,只是让材质自身显示该颜色,比如设为0xff0000,物体会带红色发光效果;
  3. emissiveIntensity:调节自发光的亮度,值越大发光越明显;
  4. flatShading: true:几何体每个面会显示纯色,无平滑过渡,适合做低多边形风格;
  5. 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
});

高光核心参数释义

  1. specular:决定高光光斑的颜色 ,比如:
    • 塑料材质:设为0xffffff(白色高光),最真实;
    • 金属材质:设为和color相同的颜色,高光和本体同色;
  2. shininess:核心高光参数,值越小 → 高光范围越大、亮度越低值越大 → 高光范围越小、亮度越高
    • 示例:shininess:5 → 大面积柔和高光;shininess:100 → 小面积刺眼高光。

注意点

  1. 同样必须添加光源,无光源则全黑;
  2. Phong的高光效果是模拟的光泽,不是物理真实的,高光光斑略显生硬,但性能不错,适合简单光泽场景;
  3. 该材质的高光计算在顶点上,低面数几何体的高光会有锯齿。

四、物理基础材质 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个)

这是该材质的灵魂,记住取值范围+含义,就能调出所有质感,无任何例外!

  1. roughness (粗糙度) 0~1
    • 0 → 镜面级光滑,反射所有光线,高光极强(比如镜子、抛光金属);
    • 1 → 完全粗糙,无任何高光,纯哑光(比如纸张、水泥);
    • 中间值 → 半光泽(比如塑料、漆面、木头)。
  2. metalness (金属度) 0~1
    • 0 → 非金属材质(塑料、玻璃、石头、布料),反射环境光,高光颜色固定;
    • 1 → 纯金属材质(金、银、铜),反射自身颜色,高光和本体同色;
    • 中间值 → 合金材质(比如不锈钢、黄铜)。
  3. emissive + emissiveIntensity:自发光,不会照亮其他物体,比如霓虹灯、指示灯、发光logo。
  4. 颜色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;控制玻璃/水的折射效果
});

专属参数核心释义

  1. sheen:丝绸/天鹅绒的核心参数,能实现「反向高光」,布料的质感全靠它;
  2. iridescence:彩虹色散,珍珠、肥皂泡、车漆的金属珠光效果,必调参数;
  3. anisotropy:拉丝金属的核心,比如不锈钢拉丝面板、头发,高光会沿着拉丝方向延伸;
  4. 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);

核心参数

  1. size:粒子的像素大小,值越大粒子越大;
  2. sizeAttenuation: true:粒子会像真实物体一样,离相机越近越大,越远越小,必开;
  3. 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);

注意点

  1. 虚线材质必须调用 geometry.computeLineDistances(),否则会显示为实线,无虚线效果;
  2. 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, // 建议关闭,避免阴影闪烁
});

使用注意点

  1. 必须开启光源的阴影投射 + 物体的阴影投射 + 地面的阴影接收

    javascript 复制代码
    directionalLight.castShadow = true; // 光源投射阴影
    cube.castShadow = true; // 物体投射阴影
    ground.receiveShadow = true; // 地面接收阴影
  2. 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,
});

核心参数释义

  1. vertexShader:顶点着色器,运行在GPU上,控制每个顶点的位置、法线、纹理坐标等;
  2. fragmentShader:片元着色器,运行在GPU上,控制每个像素的最终颜色,所有视觉特效都在这里实现;
  3. uniforms:JS和GLSL之间的数据桥梁 ,可以在JS中动态修改uniforms.uTime.value,GLSL中就能实时获取,实现动画。

注意点

  • Three.js会自动注入内置变量 (比如projectionMatrixmodelViewMatrix),无需手动声明;
  • 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. 材质使用优先级(按推荐度排序)

  1. 优先用 MeshStandardMaterial → 99%场景够用,物理真实、参数简单、性能均衡;
  2. 需要极致细节 → 用 MeshPhysicalMaterial
  3. 调试几何体 → 用 MeshBasicMaterial
  4. 简单哑光物体+低性能设备 → 用 MeshLambertMaterial
  5. 简单光泽物体 → 用 MeshPhongMaterial
  6. 粒子/点云 → 用 PointsMaterial
  7. 线条 → 用 LineBasicMaterial/LineDashedMaterial
  8. 2D精灵/图标 → 用 SpriteMaterial
  9. 透明地面+阴影 → 用 ShadowMaterial
  10. 自定义特效 → 用 ShaderMaterial/RawShaderMaterial

2. 核心记忆点

  • 所有网格材质共用一套公共参数,无需重复记忆;
  • PBR材质的核心是「粗糙度+金属度」,记住0~1的取值规则,就能调出所有质感;
  • 材质可以复用,多个物体用同一个材质能极大优化性能;
  • 透明材质建议开启 transparent:true + depthWrite:false,避免闪烁/穿透问题。
相关推荐
Kratzdisteln2 小时前
【1902】预先生成完整的树状PPT结构
java·前端·powerpoint
深耕AI2 小时前
【wordpress系列教程】05 文章分类与标签
前端
michael_ouyang3 小时前
WebSocket 鉴权方案选型与 Electron 应用的最佳实践
前端·websocket·网络协议·electron
xixixin_3 小时前
【vue】中字符串与数组转换:为何首选 Computed 而非 Methods?
前端·javascript·vue.js
Sylvia33.3 小时前
网球/羽毛球数据API:专业赛事数据服务的技术实现
java·前端·websocket·json
向下的大树3 小时前
VUE父子组件传参中的触发时机问题:异步场景下的解决方案
前端·javascript·vue.js
英俊潇洒美少年3 小时前
vue2中使用节流防抖函数时,使用的vue状态始终是初始化的数据
前端·javascript·vue.js
棒棒的唐3 小时前
适合小程序使用的将对象数组转换为参数字符串方法
前端·javascript·小程序
博客zhu虎康4 小时前
音频视频处理:前端直播流播放 flv
前端