一、材质是什么?
简单来说,材质定义了物体表面的视觉属性——颜色、光泽度、透明度、对光的反应方式等等。在 Three.js 中,材质是 Material 类的实例,它和几何体(Geometry)一起构成了网格(Mesh):
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);
二、设置材质属性的两种方式
方式一:创建时传入配置对象
const material = new THREE.MeshPhongMaterial({
color: 0xFF0000, // 红色
flatShading: true, // 平面着色
});
方式二:创建后动态修改
const material = new THREE.MeshPhongMaterial();
material.color.setHSL(0, 1, 0.5); // 红色
material.flatShading = true;
颜色的多种设置方式
Three.js 的颜色系统非常灵活,THREE.Color 支持多种赋值方式:
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
创建材质时也一样灵活:
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 元素、线框展示、或者你只是想快速看到一个物体。
const material = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
2. MeshLambertMaterial —— Lambert 材质
特点:在顶点处计算光照。
Lambert 材质使用 Lambertian 反射模型,只在几何体的顶点处计算光照,然后在三角面内做插值。它能表现出基本的明暗效果,但不支持高光(specular highlight)。
const material = new THREE.MeshLambertMaterial({ color: 0x44aa88 });
由于只在顶点计算光照,在低多边形(Low-Poly)模型上可能会看到明显的色块分界。
3. MeshPhongMaterial —— Phong 材质
特点:在每个像素处计算光照,支持高光。
Phong 材质比 Lambert 更精细,它在每个像素上都计算光照,因此能产生平滑的光照过渡和镜面高光(specular highlight)效果。
const material = new THREE.MeshPhongMaterial({
color: 0x44aa88,
shininess: 100, // 高光强度,默认 30
});
shininess 参数控制高光的集中程度:
shininess: 0—— 没有高光,效果类似 Lambertshininess: 30—— 默认值,柔和的高光shininess: 150—— 强烈集中的高光,类似抛光表面
emissive 属性的妙用
MeshLambertMaterial 和 MeshPhongMaterial 都有 emissive(自发光)属性。当你把 color 设为黑色,emissive 设为某个颜色时,效果会和 MeshBasicMaterial 几乎一样:
// 以下三种方式视觉效果基本相同
new THREE.MeshBasicMaterial({ color: 'purple' });
new THREE.MeshLambertMaterial({ color: 'black', emissive: 'purple' });
new THREE.MeshPhongMaterial({ color: 'black', emissive: 'purple', shininess: 0 });
4. MeshToonMaterial —— 卡通材质
特点:类似 Phong,但使用渐变贴图实现卡通风格的色阶着色。
卡通材质不会平滑过渡光影,而是使用渐变贴图将光照分成几个离散的色阶,营造出二维卡通的视觉效果。
const material = new THREE.MeshToonMaterial({ color: 0x44aa88 });
默认的渐变贴图在前 70% 亮度区域使用 70% 的明度,之后跳到 100%,形成经典的双色阶卡通效果。你也可以提供自定义的渐变贴图来实现更丰富的色阶。
5. MeshStandardMaterial —— 标准 PBR 材质
特点:基于物理渲染(PBR),使用 roughness 和 metalness 参数。
这是 Three.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(清漆粗糙度)参数,可以模拟汽车漆面、贴膜表面等具有多层反射的材质。
const material = new THREE.MeshPhysicalMaterial({
color: 0x44aa88,
roughness: 0.5,
metalness: 0.5,
clearcoat: 1.0, // 清漆强度 0~1
clearcoatRoughness: 0.1, // 清漆粗糙度 0~1
});
四、性能排序:如何选择合适的材质?
不同材质的 GPU 开销差异显著,从快到慢排列:
MeshBasicMaterial → MeshLambertMaterial → MeshPhongMaterial → MeshStandardMaterial → MeshPhysicalMaterial
最快 最慢
(无光照) (顶点光照) (像素光照) (PBR) (PBR + 清漆层)
五、通用材质属性
所有材质都继承自 Material 基类,以下两个属性最常用:
flatShading(平面着色)
控制物体表面看起来是棱角分明还是光滑圆润。
material.flatShading = true; // 每个三角面使用统一法线,呈现硬朗的多面体效果
material.flatShading = false; // 默认,法线在三角面间插值,呈现平滑效果
side(渲染面)
控制三角面的哪一侧会被渲染:
material.side = THREE.FrontSide; // 默认,只渲染正面
material.side = THREE.BackSide; // 只渲染背面
material.side = THREE.DoubleSide; // 双面渲染
大多数 3D 物体是封闭实体,背面不可见,不需要渲染。但对于平面(Plane)、开放曲面等可能看到背面的几何体,应设为 THREE.DoubleSide。
核心代码与完整示例: my-three-app
总结
如果你喜欢本教程,记得点赞+收藏!关注我获取更多Three.js开发干货