Three.js 材质完全入门指南:让你的 3D 物体「活」起来

一、材质是什么?

简单来说,材质定义了物体表面的视觉属性 ------颜色、光泽度、透明度、对光的反应方式等等。在 Three.js 中,材质是 Material 类的实例,它和几何体(Geometry)一起构成了网格(Mesh):

js 复制代码
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshPhongMaterial({ color: 0xFF0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

二、设置材质属性的两种方式

方式一:创建时传入配置对象

js 复制代码
const material = new THREE.MeshPhongMaterial({
  color: 0xFF0000,    // 红色
  flatShading: true,  // 平面着色
});

方式二:创建后动态修改

js 复制代码
const material = new THREE.MeshPhongMaterial();
material.color.setHSL(0, 1, 0.5);  // 红色
material.flatShading = true;

颜色的多种设置方式

Three.js 的颜色系统非常灵活,THREE.Color 支持多种赋值方式:

js 复制代码
material.color.set(0x00FFFF);            // 十六进制
material.color.set('purple');             // CSS 颜色名
material.color.set('#F32');               // CSS 缩写
material.color.set('rgb(255, 127, 64)'); // RGB 函数
material.color.set('hsl(180, 50%, 25%)'); // HSL 函数
material.color.setHSL(h, s, l);          // h, s, l 范围 0~1
material.color.setRGB(r, g, b);          // r, g, b 范围 0~1

创建材质时也一样灵活:

js 复制代码
new THREE.MeshBasicMaterial({ color: 0xFF0000 });          // 十六进制
new THREE.MeshBasicMaterial({ color: 'red' });             // 颜色名
new THREE.MeshBasicMaterial({ color: '#F00' });            // CSS 缩写
new THREE.MeshBasicMaterial({ color: 'rgb(255,0,0)' });    // RGB
new THREE.MeshBasicMaterial({ color: 'hsl(0,100%,50%)' }); // HSL

三、六大核心材质类型详解

1. MeshBasicMaterial ------ 基础材质

特点:不受光照影响。

这是最简单的材质,物体始终以纯色显示,不管场景中有没有灯光。适合用于不需要光影效果的场景,比如 UI 元素、线框展示、或者你只是想快速看到一个物体。

js 复制代码
const material = new THREE.MeshBasicMaterial({ color: 0x44aa88 });

2. MeshLambertMaterial ------ Lambert 材质

特点:在顶点处计算光照。

Lambert 材质使用 Lambertian 反射模型,只在几何体的顶点处计算光照,然后在三角面内做插值。它能表现出基本的明暗效果,但不支持高光(specular highlight)

js 复制代码
const material = new THREE.MeshLambertMaterial({ color: 0x44aa88 });

由于只在顶点计算光照,在低多边形(Low-Poly)模型上可能会看到明显的色块分界。

3. MeshPhongMaterial ------ Phong 材质

特点:在每个像素处计算光照,支持高光。

Phong 材质比 Lambert 更精细,它在每个像素上都计算光照,因此能产生平滑的光照过渡和镜面高光(specular highlight)效果。

js 复制代码
const material = new THREE.MeshPhongMaterial({
  color: 0x44aa88,
  shininess: 100, // 高光强度,默认 30
});

shininess 参数控制高光的集中程度:

  • shininess: 0 ------ 没有高光,效果类似 Lambert
  • shininess: 30 ------ 默认值,柔和的高光
  • shininess: 150 ------ 强烈集中的高光,类似抛光表面

emissive 属性的妙用

MeshLambertMaterialMeshPhongMaterial 都有 emissive(自发光)属性。当你把 color 设为黑色,emissive 设为某个颜色时,效果会和 MeshBasicMaterial 几乎一样:

js 复制代码
// 以下三种方式视觉效果基本相同
new THREE.MeshBasicMaterial({ color: 'purple' });

new THREE.MeshLambertMaterial({ color: 'black', emissive: 'purple' });

new THREE.MeshPhongMaterial({ color: 'black', emissive: 'purple', shininess: 0 });

4. MeshToonMaterial ------ 卡通材质

特点:类似 Phong,但使用渐变贴图实现卡通风格的色阶着色。

卡通材质不会平滑过渡光影,而是使用渐变贴图将光照分成几个离散的色阶,营造出二维卡通的视觉效果。

js 复制代码
const material = new THREE.MeshToonMaterial({ color: 0x44aa88 });

默认的渐变贴图在前 70% 亮度区域使用 70% 的明度,之后跳到 100%,形成经典的双色阶卡通效果。你也可以提供自定义的渐变贴图来实现更丰富的色阶。

5. MeshStandardMaterial ------ 标准 PBR 材质

特点:基于物理渲染(PBR),使用 roughnessmetalness 参数。

这是 Three.js 中最常用的高质量材质。它基于物理的光照模型,能更真实地模拟现实世界中光线与材质的交互。

js 复制代码
const material = new THREE.MeshStandardMaterial({
  color: 0x44aa88,
  roughness: 0.5, // 粗糙度 0~1
  metalness: 0.5, // 金属度 0~1
});

两个关键参数:

参数 范围 含义
roughness 0 ~ 1 表面粗糙度。0 = 光滑如镜(台球),1 = 完全粗糙(棒球)
metalness 0 ~ 1 金属感。0 = 非金属(塑料、木头),1 = 纯金属(铁、金)

roughness 可以理解为 shininess 的反义词------roughness 越高,表面越粗糙,反射越模糊。

6. MeshPhysicalMaterial ------ 物理材质

特点:在 Standard 材质基础上增加了清漆层(Clearcoat)。

物理材质是标准材质的增强版,额外提供了 clearcoat(清漆)和 clearcoatRoughness(清漆粗糙度)参数,可以模拟汽车漆面、贴膜表面等具有多层反射的材质。

js 复制代码
const material = new THREE.MeshPhysicalMaterial({
  color: 0x44aa88,
  roughness: 0.5,
  metalness: 0.5,
  clearcoat: 1.0,            // 清漆强度 0~1
  clearcoatRoughness: 0.1,   // 清漆粗糙度 0~1
});

四、性能排序:如何选择合适的材质?

不同材质的 GPU 开销差异显著,从快到慢排列:

markdown 复制代码
MeshBasicMaterial → MeshLambertMaterial → MeshPhongMaterial → MeshStandardMaterial → MeshPhysicalMaterial
      最快                                                                                    最慢
    (无光照)         (顶点光照)          (像素光照)         (PBR)                (PBR + 清漆层)

五、通用材质属性

所有材质都继承自 Material 基类,以下两个属性最常用:

flatShading(平面着色)

控制物体表面看起来是棱角分明还是光滑圆润。

js 复制代码
material.flatShading = true;  // 每个三角面使用统一法线,呈现硬朗的多面体效果
material.flatShading = false; // 默认,法线在三角面间插值,呈现平滑效果

side(渲染面)

控制三角面的哪一侧会被渲染:

js 复制代码
material.side = THREE.FrontSide;  // 默认,只渲染正面
material.side = THREE.BackSide;   // 只渲染背面
material.side = THREE.DoubleSide; // 双面渲染

大多数 3D 物体是封闭实体,背面不可见,不需要渲染。但对于平面(Plane)、开放曲面 等可能看到背面的几何体,应设为 THREE.DoubleSide

核心代码与完整示例: my-three-app

总结

如果你喜欢本教程,记得点赞+收藏!关注我获取更多Three.js开发干货

相关推荐
cTz6FE7gA1 天前
WebGL实战:用Three.js创建3D场景,实现沉浸式Web体验
前端·javascript·webgl
三维搬砖者6 天前
AI 解密大厂 Three.js 三维引擎开发 03|从经纬度到三维世界的坐标解码
webgl·three.js
threelab10 天前
引擎案例分析 02|GeoLayer 大厂地理可视化方案深度拆解
javascript·3d·webgl
山海鲸可视化10 天前
【山海鲸功能演示】如何设置选中按钮的时候其他按钮切换为默认样式?
webgl·可视化·数据可视化·数据表格·搜索框
kadog10 天前
GraphX:基于 WebGL 区间算术的 GPU 加速隐函数绘图器
前端·javascript·数学建模·webgl
ct97811 天前
Cesium的Primitive API
gis·webgl·cesium
一马平川的大草原14 天前
基于Vue+Three.js实现三维油藏模型解析与可视化交互切割操作
vue.js·three.js·三维油藏模型
sin°θ_陈14 天前
前馈式3D Gaussian Splatting 研究地图(路线二):几何优先的前馈式 3DGS——前馈式 3DGS 如何重新拥抱多视图几何
深度学习·3d·webgl·三维重建·空间计算·3dgs·空间智能
RulerMike15 天前
three 实现简单机械臂逆运动
前端·ai编程·three.js