1、Three.js材质系统概述:材质(Material)的概念、材质与渲染的关系、材质分类(基础、标准、物理等)

好,我们正式开始Three.js材质与光照系统的学习。第一章,先聊聊材质到底是什么。

你想想看,一个3D模型在屏幕上显示出来,光有几何形状是不够的。它是什么颜色?表面粗糙还是光滑?有没有金属质感?这些信息,就是由材质来定义的。

我个人习惯把材质理解为「物体的皮肤」。它决定了物体如何与光线互动,最终呈现出什么样的视觉效果。

材质(Material)的概念

在Three.js里,材质是一个对象。它包含了渲染一个几何体所需的所有视觉属性。比如颜色、透明度、粗糙度、金属度、贴图等等。

说白了,材质就是一组参数的集合。这些参数告诉渲染器:「嘿,这个物体看起来应该像塑料,那个应该像金属,远处的那个应该半透明。」

我记得刚接触Three.js时,以为材质就是给模型上个颜色。后来才发现,材质的世界远比想象中复杂。一个简单的颜色属性背后,牵扯到光照计算、着色器、纹理映射等一系列底层机制。

核心概念:材质 = 视觉属性的集合 + 渲染行为的定义

材质与渲染的关系

材质和渲染的关系,就像菜谱和厨师的关系。材质提供了「怎么做」的指令,渲染器负责「执行」这些指令。

具体来说,Three.js的渲染流程是这样的:

  1. 场景中有几何体、光源、相机
  2. 渲染器遍历场景中的每个物体
  3. 对于每个物体,读取其材质参数
  4. 根据材质类型,选择对应的着色器程序
  5. 将材质参数传递给着色器
  6. 着色器计算每个像素的颜色
  7. 最终输出到屏幕

嗯,这里要注意:材质的选择直接影响渲染性能。我在项目中遇到过,一个复杂的物理材质,渲染开销可能是基础材质的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不把所有材质都做成物理材质?毕竟物理材质效果最好。想想看,答案其实就在性能那一节里。