跳到主要内容
3D Playground
Three.js 核心第 3 / 13 节

材质大比拼

入门WebGL

材质决定“怎么算颜色”

几何体决定形状,材质决定每个像素的颜色怎么计算。three.js 会把材质编译成一对着色器(GLSL 程序)。不同材质的区别,本质上是光照公式不同、计算量不同。

从便宜到昂贵

  1. MeshBasicMaterial:不受光照影响,只输出颜色或贴图。适合 UI、发光体、调试。
  2. MeshLambertMaterial:只有漫反射(哑光),没有高光。计算便宜,适合大面积的粗糙表面。
  3. MeshPhongMaterial:漫反射 + 镜面高光,用 shininess 控制高光的锐利程度。经典但不“物理”。
  4. MeshStandardMaterial:基于物理的渲染(PBR),用 roughness(粗糙度)和 metalness(金属度)两个直观参数描述表面,在任何光照下都更可信。
  5. MeshPhysicalMaterial:Standard 的扩展,额外支持清漆层 clearcoat、光泽 sheen、透射、虹彩等,效果最好也最贵。

还有两个风格化/调试材质:

  • MeshToonMaterial:卡通渲染,用一张很小的 gradientMap 把连续的明暗切成几条色带。示例用 3 个像素的 DataTexture,并设置 NearestFilter 防止色带被插值模糊。
  • MeshNormalMaterial:把法线方向直接映射成 RGB,不需要灯光,常用来检查法线是否正确。

为什么金属需要环境贴图

金属几乎没有漫反射,它的颜色来自反射周围环境。如果场景里只有几盏点光源,把 metalness 拉到 1 会看到物体几乎全黑。示例给场景设置了 scene.environment(由 RoomEnvironment 生成),只有 Standard / Physical 会自动使用它,所以调高 metalness 时它们依然好看。

修改材质的小规则

大多数数值(颜色、roughness、shininess)改了立即生效;但会改变着色器代码的属性,比如 flatShading,需要设置 material.needsUpdate = true 让 three.js 重新编译。

拖动 metalness 和 roughness,观察 Standard 与 Physical 的变化,而 Lambert、Phong 完全不受影响。

核心 API

THREE.MeshBasicMaterialTHREE.MeshLambertMaterialTHREE.MeshPhongMaterialTHREE.MeshStandardMaterialTHREE.MeshPhysicalMaterialTHREE.MeshToonMaterialTHREE.MeshNormalMaterialmaterial.needsUpdatescene.environment

动手试试

  1. 1把 envIntensity 调到 0,再把 metalness 拉到 1,看看 Standard 和 Physical 为什么变黑。
  2. 2给 toonRamp 增加到 5 个灰度级,让卡通色带更细。
  3. 3把 Physical 的 clearcoat 设为 1、roughness 设为 0.8,做出“磨砂底 + 亮面漆”的效果。
  4. 4给 Phong 材质设置 emissive: "#330022",观察自发光如何叠加在光照之上。
运行中