4、物理材质(MeshPhysicalMaterial):clearcoat、sheen、transmission等高级属性、真实感渲染的利器。
好,咱们继续深入。前面聊了标准材质,它已经能搞定大部分日常需求了。但如果你想让画面「活」起来,让物体看起来像是真实存在的,那你就得请出今天的主角——MeshPhysicalMaterial。
说白了,它就是 Three.js 材质体系里的「顶配」。我个人的习惯是,只要项目对性能要求不是极端苛刻,但凡涉及到高光、透明、或者那种「高级感」的物体,我直接上物理材质。为什么?因为它内置了太多真实世界的光学模拟参数,省去了我们自己写 Shader 的麻烦。
4.1 为什么需要物理材质?
标准材质(MeshStandardMaterial)已经能模拟粗糙度和金属感了,对吧?但真实世界远比这复杂。
你想想看,一辆崭新的汽车车漆,表面那层清漆(Clear Coat)带来的额外高光;一件丝绸衬衫表面那层细密的绒毛(Sheen)产生的柔光;还有一块通透的玉石,光线穿过内部再散射出来的效果(Transmission)。
这些效果,标准材质是搞不定的。物理材质就是为这些「刁钻」需求而生的。它基于更复杂的物理模型,计算量更大,但效果也绝对对得起那点性能开销。
4.2 三大高级属性详解
咱们一个一个来拆解。这三个属性是我在实际项目中用得最多的,也是最能拉开画面差距的地方。
4.2.1 clearcoat(清漆层)
这个属性模拟的是物体表面额外覆盖的一层透明薄膜。最典型的例子就是汽车漆、木器漆、或者塑料外壳。
它的原理是:在基础材质之上,再叠加一层微小的菲涅尔高光。这层高光不受基础材质的粗糙度影响,独立存在。
// 创建一个带有清漆效果的材质
const material = new THREE.MeshPhysicalMaterial({
color: 0x0044ff,
metalness: 0.3,
roughness: 0.4,
clearcoat: 1.0, // 清漆强度,范围 0-1
clearcoatRoughness: 0.1 // 清漆层的粗糙度,0 为镜面,1 为磨砂
});
我在项目中遇到过一个做汽车展示的需求。客户要求车漆看起来「润」,但又不能是镜面反射那种死硬的感觉。我调了半天 roughness 都不对,后来加上 clearcoat: 0.8 和 clearcoatRoughness: 0.15,瞬间就有了那种「表面有一层油润感」的质感。嗯,这里要注意,clearcoatRoughness 别设成 0,否则高光会像塑料片一样刺眼。
4.2.2 sheen(光泽层)
Sheen 模拟的是织物、天鹅绒、或者某些水果表面那层细小的绒毛产生的光泽。这种光泽的特点是:从正面看很柔和,从掠射角看会有一层淡淡的彩色光晕。
说白了,它就是在物体边缘添加了一层额外的、带颜色的高光。
// 模拟一块红色天鹅绒布料
const material = new THREE.MeshPhysicalMaterial({
color: 0xcc0000,
roughness: 0.8,
metalness: 0,
sheen: 1.0, // 开启光泽层
sheenColor: new THREE.Color(0xffaa00), // 绒毛反射的颜色,这里是暖金色
sheenRoughness: 0.4 // 绒毛的粗糙度
});
我曾经在做一个室内软装项目时,需要表现沙发面料的质感。直接用标准材质调 roughness,出来的效果要么像塑料,要么像磨砂石头。后来换成物理材质,加上 sheen 并给了一个偏暖的 sheenColor,那种「绒布感」一下子就出来了。你想想看,如果没有这个属性,你得写多少 Shader 代码才能模拟出这种效果?
4.2.3 transmission(透射率)
这个属性是物理材质里最「黑科技」的一个。它模拟的是光线穿过透明物体的效果,比如玻璃、水晶、玉石、塑料瓶。
注意,它和 opacity 完全不同。opacity 只是简单地把物体变透明,光线不会发生折射、散射。而 transmission 会计算光线进入物体、穿过物体、再从另一侧射出的完整路径。
// 创建一个真实的玻璃球
const material = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 1.0, // 完全透射
thickness: 0.5, // 物体厚度,影响折射扭曲程度
ior: 1.5, // 折射率,玻璃约为 1.5
envMap: envTexture, // 环境贴图,必须有!否则透射效果不完整
envMapIntensity: 1.0
});
我个人习惯是,只要做玻璃或透明塑料,必用 transmission。但这里有个大坑:它必须配合环境贴图(envMap)才能生效。没有环境贴图,transmission 材质看起来就是一团黑乎乎的透明物体,毫无质感。
为什么会这样?因为透射材质需要知道「光线从物体背后穿过来时,应该看到什么」。环境贴图提供了这个「背后」的信息。
| 参数 | 作用 | 典型值 |
|---|---|---|
| transmission | 透射强度,0为不透明,1为完全透明 | 0.9 - 1.0 |
| thickness | 模拟物体厚度,影响折射扭曲和色散 | 0.1 - 1.0 |
| ior | 折射率,决定光线弯曲程度 | 1.0 (空气) / 1.33 (水) / 1.5 (玻璃) / 2.4 (钻石) |
| envMap | 环境贴图,提供透射背景 | 必须设置 |
4.3 真实感渲染的实战组合
光讲参数没意思,咱们来点实际的。我总结了一套「真实感三件套」的配置思路,你可以直接套用。
- 环境贴图是灵魂:没有 envMap,物理材质的效果直接打五折。我建议使用 HDR 环境贴图,它能提供更丰富的光照信息。
- 合理搭配 roughness 和 metalness:物理材质虽然高级,但基础属性依然重要。金属材质 roughness 要低,非金属材质 roughness 要高。
- 高级属性按需开启:不要为了炫技而滥用。clearcoat 用在漆面,sheen 用在织物,transmission 用在透明体。用错了反而会显得假。
// 一个完整的「高级塑料外壳」示例
const material = new THREE.MeshPhysicalMaterial({
color: 0x222222,
metalness: 0.1,
roughness: 0.3,
clearcoat: 0.8,
clearcoatRoughness: 0.05,
envMap: hdrEquirectangularReflectionTexture,
envMapIntensity: 1.5
});
你看,代码量不大,但效果绝对比标准材质高出一个档次。我在做产品展示项目时,这种配置几乎是标配。
material.onBeforeCompile 进行自定义优化,或者考虑使用 LOD(细节层次)来降低远处物体的材质复杂度。
好了,关于物理材质的高级属性,咱们就聊到这里。记住,工具再好,也要看你怎么用。多观察真实世界中的材质表现,再回到代码里调整参数,这才是提升渲染质量的捷径。