Three.js 材质进阶

概述

本文档将介绍Three.js中材质的进阶用法,包括各种高级材质类型、材质属性设置、环境贴图、透明效果等重要概念。通过这些知识点,您将能够创建更加真实和富有表现力的3D场景。

第一部分:MatCap材质

1. MatCap材质的概念

MatCap(Material Capture)材质是一种特殊的材质类型,它预先渲染了材质的光照效果到一张纹理上,因此具有很高的性能效率。MatCap材质非常适合用于实时渲染中需要高质量光照效果但又不想消耗过多性能的场景。

2. 基本使用方法

javascript 复制代码
// 加载MatCap纹理
let matcapTexture = new THREE.TextureLoader().load(
  "./texture/matcaps/54584E_B1BAC5_818B91_A7ACA3-512px.png"
);

// 创建MatCap材质
let material = new THREE.MeshMatcapMaterial({
  matcap: matcapTexture,
  map: preMaterial.map,  // 可以同时使用其他纹理
});

// 应用到网格对象
duckMesh.material = material;

3. MatCap材质的优势

  • 性能优异:无需实时计算光照
  • 效果逼真:预渲染的光照效果非常真实
  • 使用简单:只需要一张纹理即可实现复杂的光照效果

第二部分:Lambert和Phong材质

1. Lambert材质

Lambert材质是一种漫反射材质,它模拟的是理想漫反射表面,适用于不光滑的表面。

javascript 复制代码
let planeMaterial = new THREE.MeshLambertMaterial({
  map: colorTexture,           // 颜色贴图
  specularMap: specularTexture, // 高光贴图
  transparent: true,           // 透明度
  normalMap: normalTexture,    // 法线贴图
  bumpMap: dispTexture,        // 凹凸贴图
  displacementMap: dispTexture, // 位移贴图
  displacementScale: 0.02,     // 位移缩放
  aoMap: aoTexture,            // 环境光遮蔽贴图
});

2. Phong材质

Phong材质是一种更高级的材质,它可以计算镜面高光,适用于光滑表面。

javascript 复制代码
let planeMaterial = new THREE.MeshPhongMaterial({
  map: colorTexture,
  specularMap: specularTexture,
  transparent: true,
  normalMap: normalTexture,
  bumpMap: dispTexture,
  displacementMap: dispTexture,
  displacementScale: 0.02,
  aoMap: aoTexture,
});

3. 两者的区别

  • Lambert材质:只计算漫反射,没有镜面高光
  • Phong材质:计算漫反射和镜面高光,更适合光滑表面

第三部分:Phong材质制作玻璃和水晶效果

1. 玻璃效果的实现

javascript 复制代码
// 使用折射环境贴图
envMap.mapping = THREE.EquirectangularRefractionMapping;

duckMesh.material = new THREE.MeshPhongMaterial({
  map: preMaterial.map,
  refractionRatio: 0.7,   // 折射率
  reflectivity: 0.99,     // 反射率
  envMap: envMap,         // 环境贴图
});

2. 参数调节

  • refractionRatio:控制折射程度,值越大折射越明显
  • reflectivity:控制反射强度,接近1.0时反射效果更强

第四部分:Standard材质详解

Standard材质(MeshStandardMaterial)是Three.js中最常用的PBR(基于物理的渲染)材质之一。

1. 基本属性

javascript 复制代码
// Standard材质的主要属性
const material = new THREE.MeshStandardMaterial({
  color: 0xffffff,              // 基础颜色
  roughness: 0.5,               // 粗糙度 (0-1)
  metalness: 0.5,               // 金属度 (0-1)
  map: texture,                 // 颜色贴图
  normalMap: normalTexture,     // 法线贴图
  roughnessMap: roughnessTexture, // 粗糙度贴图
  metalnessMap: metalnessTexture, // 金属度贴图
  aoMap: aoTexture,             // 环境光遮蔽贴图
  envMap: envMap,               // 环境贴图
});

2. 动态控制材质属性

javascript 复制代码
// 通过GUI动态控制材质属性
let params = {
  aoMap: true,
};

gui.add(params, "aoMap").onChange((value) => {
  mesh.material.aoMap = value ? aoMap : null;
  mesh.material.needsUpdate = true;  // 需要更新材质
});

第五部分:透光性、厚度、衰减颜色和衰减距离

1. 物理材质的透光效果

MeshPhysicalMaterial支持更高级的透光效果,可以模拟玻璃、钻石等材质。

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial({
  transparent: true,                    // 启用透明
  transmission: 0.95,                   // 透射率 (0-1)
  roughness: 0.05,                      // 粗糙度
  thickness: 2,                         // 厚度
  attenuationColor: new THREE.Color(0.9, 0.9, 0), // 衰减颜色
  attenuationDistance: 1,               // 衰减距离
  thicknessMap: thicknessMap,           // 厚度贴图
});

2. 参数说明

  • transmission:透射率,值越高越透明
  • thickness:厚度,影响光线穿过物体的方式
  • attenuationColor:光线在物体内部传播时的颜色变化
  • attenuationDistance:光线在物体内部传播的距离

3. 通过GUI调节参数

javascript 复制代码
gui.add(material, "attenuationDistance", 0, 10).name("衰减距离");
gui.add(material, "thickness", 0, 2).name("厚度");

第六部分:折射率和反射率

1. 折射率(IOR)

折射率(Index of Refraction)决定了光线穿过材质时的弯曲程度。

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial({
  transparent: true,
  transmission: 0.95,
  roughness: 0.05,
  thickness: 2,
  attenuationColor: new THREE.Color(0.9, 0.9, 0),
  attenuationDistance: 1,
  ior: 1.5,                // 折射率
});

// 通过GUI调节折射率
gui.add(material, "ior", 0, 2).name("折射率");

2. 反射率

反射率控制材质表面的反射强度。

javascript 复制代码
// 设置反射率
material.reflectivity = 0.9;

// 通过GUI调节反射率
gui.add(material, "reflectivity", 0, 1).name("反射率");

3. 常见材质的折射率参考

  • 空气:1.0
  • 水:1.33
  • 玻璃:1.5
  • 钻石:2.4

第七部分:清漆、清漆法向和清漆粗糙度

1. 清漆效果

清漆(Clearcoat)属性可以模拟材质表面的额外涂层,如汽车漆面或家具上的清漆层。

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial({
  transparent: true,
  color: 0xffff00,                  // 基础颜色
  roughness: 0.5,                   // 基础粗糙度
  clearcoat: 1,                     // 清漆强度 (0-1)
  clearcoatRoughness: 0,            // 清漆粗糙度 (0-1)
  clearcoatMap: thicknessMap,       // 清漆贴图
  clearcoatRoughnessMap: thicknessMap, // 清漆粗糙度贴图
  clearcoatNormalMap: scratchNormal, // 清漆法线贴图
  normalMap: carbonNormal,          // 基础法线贴图
  clearcoatNormalScale: new THREE.Vector2(0.1, 0.1), // 清漆法线缩放
});

2. 清漆相关属性

  • clearcoat:清漆层的强度
  • clearcoatRoughness:清漆层的粗糙度
  • clearcoatNormalMap:清漆层的法线贴图
  • clearcoatNormalScale:清漆法线贴图的缩放

第八部分:布料和织物材料光泽效果

1. Sheen属性

Sheen属性用于模拟织物等材料的光泽效果,特别适合制作布料、丝绸等材质。

javascript 复制代码
const sphereMaterial = new THREE.MeshPhysicalMaterial({
  color: 0x222288,              // 基础颜色
  sheen: 1,                     // 光泽强度 (0-1)
  sheenColor: 0xffffff,         // 光泽颜色
  roughness: 1,                 // 粗糙度
  sheenRoughness: 1,            // 光泽粗糙度
  sheenColorMap: brickRoughness, // 光泽颜色贴图
});

2. Sheen相关属性

  • sheen:光泽效果的强度
  • sheenColor:光泽的颜色
  • sheenRoughness:光泽的粗糙度
  • sheenColorMap:光泽颜色贴图

第九部分:虹彩效应(Iridescence)

1. 虹彩效果简介

虹彩效果可以模拟某些特殊材质(如肥皂泡、昆虫翅膀、油膜等)产生的彩虹色效果。

javascript 复制代码
const sphereMaterial = new THREE.MeshPhysicalMaterial({
  color: 0xffffff,                           // 基础颜色
  roughness: 0.05,                          // 粗糙度
  transmission: 1,                          // 透射率
  thickness: 0.1,                           // 厚度
  iridescence: 1,                           // 虹彩强度 (0-1)
  reflectivity: 1,                          // 反射率
  iridescenceIOR: 1.3,                      // 虹彩折射率
  iridescenceThicknessRange: [100, 400],    // 虹彩厚度范围
  iridescenceThicknessMap: brickRoughness,  // 虹彩厚度贴图
});

2. 虹彩相关属性

  • iridescence:虹彩效果强度
  • iridescenceIOR:虹彩折射率
  • iridescenceThicknessRange:虹彩厚度范围
  • iridescenceThicknessMap:虹彩厚度贴图

3. 通过GUI调节虹彩参数

javascript 复制代码
// 调节虹彩参数
gui.add(sphereMaterial, "iridescence", 0, 1).name("彩虹色");
gui.add(sphereMaterial, "reflectivity", 0, 1).name("反射率");
gui.add(sphereMaterial, "iridescenceIOR", 0, 3).name("彩虹色折射率");

// 调节虹彩厚度范围
let iridescenceThickness = {
  min: 100,
  max: 400,
};

gui
  .add(iridescenceThickness, "min", 0, 1000)
  .name("彩虹色最小厚度")
  .onChange(() => {
    sphereMaterial.iridescenceThicknessRange[0] = iridescenceThickness.min;
  });

gui
  .add(iridescenceThickness, "max", 0, 1000)
  .name("彩虹色最大厚度")
  .onChange(() => {
    sphereMaterial.iridescenceThicknessRange[1] = iridescenceThickness.max;
  });

第十部分:发光属性与发光贴图

1. 发光效果的实现

通过emissive属性可以创建自发光效果,常用于模拟屏幕、灯泡等发光物体。

javascript 复制代码
// 加载手机模型并设置发光效果
gltfLoader.load(
  "./model/mobile/scene.glb",
  (gltf) => {
    console.log(gltf);
    scene.add(gltf.scene);
    
    // 可以进一步调整屏幕等特定部分的发光效果
    let screen = gltf.scene.getObjectByName("screen"); // 假设屏幕有特定名称
    if(screen) {
      screen.material.emissive = new THREE.Color(0x00ffff); // 设置发光颜色
      screen.material.emissiveIntensity = 1; // 设置发光强度
    }
  }
);

2. 环境贴图的重要性

发光效果通常需要配合高质量的环境贴图才能达到最佳效果:

javascript 复制代码
// 加载HDR环境贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/Alex_Hart-Nature_Lab_Bones_2k.hdr", (envMap) => {
  envMap.mapping = THREE.EquirectangularRefractionMapping;
  scene.background = new THREE.Color(0x7aaff5);
  scene.environment = envMap;  // 设置场景环境贴图
});

第十一部分:控制器限制查看3D场景

1. 轨道控制器的限制设置

为了限制用户的视角范围,可以对轨道控制器设置各种限制:

javascript 复制代码
const controls = new OrbitControls(camera, renderer.domElement);

// 设置目标点
controls.target.set(0, 1.2, 0);

// 禁用平移
controls.enablePan = false;

// 设置距离限制
controls.minDistance = 3;  // 最小距离
controls.maxDistance = 5;  // 最大距离

// 设置角度限制
controls.minPolarAngle = Math.PI / 2 - Math.PI / 12;  // 垂直最小角度
controls.maxPolarAngle = Math.PI / 2;                 // 垂直最大角度

controls.minAzimuthAngle = Math.PI / 2 - Math.PI / 12;  // 水平最小角度
controls.maxAzimuthAngle = Math.PI / 2 + Math.PI / 12;  // 水平最大角度

2. 限制参数说明

  • enablePan:是否启用平移
  • minDistance/maxDistance:相机与目标点的最小/最大距离
  • minPolarAngle/maxPolarAngle:垂直旋转角度限制
  • minAzimuthAngle/maxAzimuthAngle:水平旋转角度限制

第十二部分:材质销毁

1. 资源管理的重要性

在Three.js中,及时释放不再使用的材质、纹理等资源是非常重要的,以避免内存泄漏。

javascript 复制代码
// 销毁物体的示例代码
function disposeObject(obj) {
  if (obj.geometry) {
    obj.geometry.dispose();
  }
  
  if (obj.material) {
    if (Array.isArray(obj.material)) {
      obj.material.forEach(material => {
        if (material.map) material.map.dispose();
        material.dispose();
      });
    } else {
      if (obj.material.map) obj.material.map.dispose();
      obj.material.dispose();
    }
  }
}

2. 纹理和材质的销毁

javascript 复制代码
// 销毁纹理
texture.dispose();

// 销毁材质
material.dispose();

// 销毁几何体
geometry.dispose();

总结

通过本教程,我们学习了Three.js中材质的进阶用法:

  1. MatCap材质:高效预渲染光照效果的材质类型
  2. Lambert和Phong材质:传统光照模型的两种基本材质
  3. 玻璃和水晶效果:利用折射和反射实现透明材质
  4. Standard材质:PBR渲染管线的标准材质
  5. 透光效果:实现半透明和光线穿透效果
  6. 折射率和反射率:控制光线与材质表面的交互
  7. 清漆效果:模拟表面涂层的额外反射层
  8. 光泽效果:模拟织物等材质的特殊光泽
  9. 虹彩效应:创建彩虹色的光学效果
  10. 发光效果:实现自发光材质
  11. 控制器限制:限制用户视角的交互方式
  12. 资源管理:正确销毁材质以避免内存泄漏

这些高级材质特性可以让您的3D场景更加真实和吸引人。掌握这些技术后,您可以创建出令人惊叹的视觉效果。

相关推荐
全栈王校长2 小时前
Three.js Geometry进阶
webgl·three.js
烛阴21 小时前
3D字体TextGeometry
前端·webgl·three.js
全栈王校长1 天前
Three.js 开发快速入门
three.js
全栈王校长1 天前
Three.js 环境搭建与开发初识
three.js
图素1 天前
Cesium 深入浅出 《一》WGS84、ECEF、经纬高:Cesium 世界坐标到底是什么?
webgl
supermapsupport1 天前
SuperMap GIS基础产品FAQ集锦(20260112)
webgl·supermap·iserver·idesktopx
DaMu1 天前
Dreamcore3D ARPG IDE “手搓”游戏引擎,轻量级实时3D创作工具,丝滑操作,即使小白也能轻松愉快的创作出属于你自己的游戏世界!
前端·架构·three.js
刘一说2 天前
腾讯位置服务JavaScript API GL地图组件库深度解析:Vue生态中的地理空间可视化利器
javascript·vue.js·信息可视化·webgl·webgis
烛阴3 天前
从“无”到“有”:手动实现一个 3D 渲染循环全过程
前端·webgl·three.js