3、标准材质(MeshStandardMaterial):PBR原理简介、属性详解与基础材质区别
3.1 从基础材质到标准材质:一次质的飞跃
说实话,我刚接触Three.js那会儿,用的最多的就是MeshBasicMaterial和MeshLambertMaterial。那时候做出来的东西,怎么说呢,总感觉「假假的」——塑料感太强,光照一打上去就硬邦邦的,完全没有真实世界那种细腻的质感。
后来Three.js引入了MeshStandardMaterial,我才真正体会到什么叫「次世代渲染」。它基于PBR(Physically Based Rendering,基于物理的渲染)原理,说白了就是模拟真实世界中光线与材质交互的物理规律。你想想看,现实中的金属为什么反光那么锐利?木头为什么有粗糙的漫反射?这些在PBR里都有对应的数学描述。
核心区别一句话总结:基础材质是「画」出来的效果,标准材质是「算」出来的效果。前者靠贴图欺骗眼睛,后者靠物理规律还原真实。
3.2 PBR原理:为什么它更真实?
PBR的核心思想其实不复杂。它假设所有表面都由微小的「微平面」组成,光线在这些微平面上发生反射和折射。我习惯把PBR拆成两个关键部分来理解:
- 能量守恒:反射的光 + 折射/吸收的光 = 入射光的总能量。不会出现「反射光比入射光还亮」这种违反物理的现象。
- 微平面理论:表面越粗糙,微平面的朝向越杂乱,反射光就越分散(模糊);表面越光滑,微平面越整齐,反射光就越集中(锐利)。
嗯,这里要注意,PBR并不是Three.js独有的。像Unity、Unreal Engine这些主流引擎都在用。只不过Three.js的MeshStandardMaterial把PBR简化成了几个直观的属性,让我们不用去啃那些复杂的BRDF公式。
3.3 核心属性详解:roughness、metalness、envMap
3.3.1 roughness(粗糙度)
这个属性控制表面的「光滑程度」。取值范围是0到1:
- 0:完全光滑,像镜子一样反射周围环境
- 1:完全粗糙,光线向各个方向均匀散射
我在项目中遇到过一个问题:给一个金属零件设置roughness: 0,结果渲染出来亮得刺眼,完全不像真实的金属。后来发现,真实世界的金属表面再光滑,也会有微米级的凹凸,所以roughness一般不会低于0.05。这是个很实用的经验。
// 创建一个粗糙的木头表面
const woodMaterial = new THREE.MeshStandardMaterial({
roughness: 0.8,
metalness: 0.0
});
// 创建一个光滑的陶瓷表面
const ceramicMaterial = new THREE.MeshStandardMaterial({
roughness: 0.2,
metalness: 0.0
});
3.3.2 metalness(金属度)
这个属性决定材质「像金属的程度」。同样取值范围0到1:
- 0:非金属(木头、塑料、石头、布料等)
- 1:纯金属(铁、铜、金、银等)
你想想看,金属和非金属在光学上有个本质区别:金属的反射光会带有自身的颜色(比如黄金反射黄色光),而非金属的反射光基本是白色的。这就是为什么metalness为1时,材质的颜色会直接影响反射光的色调。
我的个人习惯:大多数情况下,metalness只设0或1,很少用中间值。因为真实世界中,要么是金属,要么不是金属。半金属半非金属的东西(比如生锈的铁)应该用roughness贴图来模拟,而不是靠metalness的中间值。
3.3.3 envMap(环境贴图)
环境贴图是PBR材质的「作弊器」。它本质上是一张全景图,用来模拟材质周围的环境光照。没有环境贴图,光滑材质看起来就是黑乎乎的一团,因为Three.js默认没有全局光照。
// 加载环境贴图
const loader = new THREE.CubeTextureLoader();
const envMap = loader.load([
'px.jpg', 'nx.jpg',
'py.jpg', 'ny.jpg',
'pz.jpg', 'nz.jpg'
]);
const material = new THREE.MeshStandardMaterial({
roughness: 0.1,
metalness: 0.9,
envMap: envMap,
envMapIntensity: 1.0 // 控制环境反射的强度
});
我曾经犯过一个低级错误:加载了环境贴图但忘记设置envMapIntensity,结果反射效果淡得几乎看不见。后来查文档才发现,默认强度是1,但有些HDR环境贴图需要调到2甚至3才能看到明显效果。
3.4 与基础材质的详细对比
| 对比维度 | MeshBasicMaterial | MeshLambertMaterial | MeshStandardMaterial |
|---|---|---|---|
| 光照计算 | 无光照,纯色显示 | 漫反射光照(Lambert模型) | PBR光照(微平面+能量守恒) |
| 性能消耗 | 最低 | 中等 | 较高(但现代GPU无压力) |
| 金属感表现 | 无法表现 | 无法表现 | 通过metalness精确控制 |
| 粗糙度控制 | 无 | 无 | 通过roughness精确控制 |
| 环境反射 | 不支持 | 不支持 | 支持envMap |
| 适用场景 | UI元素、调试、纯色物体 | 简单光照场景、低配设备 | 高质量渲染、产品展示、游戏 |
避坑指南:我曾经在移动端项目里大量使用MeshStandardMaterial,结果帧率直接掉到20fps。后来发现,PBR材质在移动端的性能开销比桌面端大得多。如果你的目标平台是手机,建议在roughness和metalness上使用贴图而非纯数值,因为贴图可以复用GPU的纹理采样单元,反而比逐像素计算更高效。
3.5 实际项目中的选择策略
说了这么多,到底什么时候用标准材质,什么时候用基础材质?我总结了几条经验:
- 原型验证阶段:用
MeshBasicMaterial快速搭建场景,省去光照调试的时间。 - 低配设备或大量物体:用
MeshLambertMaterial,性能比标准材质好30%-50%。 - 产品级渲染:必须用
MeshStandardMaterial,配合HDR环境贴图,效果立竿见影。 - 特殊效果:比如玻璃、水面、金属,标准材质是唯一选择。
嗯,最后说一句。PBR不是万能的,它只是让渲染更接近真实。但有时候,艺术风格化的渲染反而需要打破PBR的规则。比如卡通渲染,用基础材质加一些骚操作,效果可能比标准材质更好。工具是死的,人是活的,对吧?