1、Three.js材质系统概述:材质(Material)的概念、材质与渲染的关系、材质分类(基础、标准、物理等)
好,我们正式开始Three.js材质与光照系统的学习。第一章,先聊聊材质到底是什么。
你想想看,一个3D模型在屏幕上显示出来,光有几何形状是不够的。它是什么颜色?表面粗糙还是光滑?有没有金属质感?这些信息,就是由材质来定义的。
我个人习惯把材质理解为「物体的皮肤」。它决定了物体如何与光线互动,最终呈现出什么样的视觉效果。
材质(Material)的概念
在Three.js里,材质是一个对象。它包含了渲染一个几何体所需的所有视觉属性。比如颜色、透明度、粗糙度、金属度、贴图等等。
说白了,材质就是一组参数的集合。这些参数告诉渲染器:「嘿,这个物体看起来应该像塑料,那个应该像金属,远处的那个应该半透明。」
我记得刚接触Three.js时,以为材质就是给模型上个颜色。后来才发现,材质的世界远比想象中复杂。一个简单的颜色属性背后,牵扯到光照计算、着色器、纹理映射等一系列底层机制。
核心概念:材质 = 视觉属性的集合 + 渲染行为的定义
材质与渲染的关系
材质和渲染的关系,就像菜谱和厨师的关系。材质提供了「怎么做」的指令,渲染器负责「执行」这些指令。
具体来说,Three.js的渲染流程是这样的:
- 场景中有几何体、光源、相机
- 渲染器遍历场景中的每个物体
- 对于每个物体,读取其材质参数
- 根据材质类型,选择对应的着色器程序
- 将材质参数传递给着色器
- 着色器计算每个像素的颜色
- 最终输出到屏幕
嗯,这里要注意:材质的选择直接影响渲染性能。我在项目中遇到过,一个复杂的物理材质,渲染开销可能是基础材质的10倍以上。所以,能用简单材质解决的问题,就别上复杂的。
避坑指南:我曾经在一个移动端项目中,所有物体都用了MeshStandardMaterial。结果帧率直接掉到20fps。后来把不需要光照的物体换成MeshBasicMaterial,帧率瞬间回到60fps。材质的选择,对性能影响巨大。
材质分类
Three.js提供了多种材质类型。我按使用频率和复杂度,把它们分成三大类:
1. 基础材质(Basic Materials)
这类材质不响应光照。说白了,就是「自发光」的。物体显示什么颜色,完全由材质本身的颜色决定,不受场景中光源的影响。
主要代表:
- MeshBasicMaterial — 最简单的材质,只显示颜色或贴图
- MeshDepthMaterial — 根据深度显示灰度
- MeshNormalMaterial — 显示法线方向,常用于调试
什么时候用基础材质?
- UI元素、辅助线、天空盒
- 不需要光照的装饰性物体
- 性能敏感的场景(比如移动端)
- 调试阶段查看模型结构
// 基础材质示例
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: false
});
2. 标准材质(Standard Materials)
这类材质响应光照,使用标准的光照模型。它们能模拟出塑料、木材、石材等常见材质的效果。
主要代表:
- MeshStandardMaterial — 基于物理的渲染(PBR),使用粗糙度-金属度工作流
- MeshPhongMaterial — 经典的Phong光照模型,支持高光
- MeshLambertMaterial — Lambert光照模型,只有漫反射,没有高光
我个人最常用的是MeshStandardMaterial。它提供了很好的视觉效果,性能也还算可以接受。
// 标准材质示例
const material = new THREE.MeshStandardMaterial({
color: 0x2194f3,
roughness: 0.4,
metalness: 0.1,
emissive: 0x000000
});
经验之谈:如果你不确定用哪种材质,默认选MeshStandardMaterial准没错。它覆盖了90%以上的日常需求。等性能出现问题,再考虑降级到MeshPhongMaterial或MeshLambertMaterial。
3. 物理材质(Physical Materials)
物理材质是标准材质的升级版。它基于更精确的物理模型,能模拟出更真实的材质效果。
主要代表:
- MeshPhysicalMaterial — 在MeshStandardMaterial基础上,增加了透明度、清漆、光泽等属性
MeshPhysicalMaterial能做什么?
- 模拟玻璃、水、冰等透明材质
- 模拟汽车漆面的清漆层
- 模拟金属表面的拉丝效果
- 模拟布料、皮革等复杂材质
// 物理材质示例
const material = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
roughness: 0.1,
metalness: 0.0,
clearcoat: 1.0, // 清漆层强度
clearcoatRoughness: 0.1, // 清漆层粗糙度
transparent: true,
opacity: 0.8,
ior: 1.5 // 折射率
});
性能警告:MeshPhysicalMaterial是Three.js中最耗性能的材质。我建议只在需要展示产品细节的场景中使用。如果场景中有大量物体,尽量用标准材质替代。
材质选择指南
为了帮你快速决策,我整理了一个简单的对照表:
| 需求场景 | 推荐材质 | 性能开销 |
|---|---|---|
| 不需要光照(UI、辅助线) | MeshBasicMaterial | 极低 |
| 简单光照(漫反射为主) | MeshLambertMaterial | 低 |
| 需要高光效果 | MeshPhongMaterial | 中等 |
| 日常开发(PBR效果) | MeshStandardMaterial | 中等 |
| 高真实感(玻璃、金属) | MeshPhysicalMaterial | 高 |
小结
这一章我们聊了材质的基本概念、材质与渲染的关系,以及三大类材质的特点和适用场景。
记住一句话:材质是视觉效果的灵魂。同样的几何体,换上不同的材质,呈现出的效果天差地别。
下一章,我们会深入MeshBasicMaterial,看看这个最简单的材质背后,藏着哪些有趣的细节。
课后思考:为什么Three.js不把所有材质都做成物理材质?毕竟物理材质效果最好。想想看,答案其实就在性能那一节里。