从零开始学习three.js(6):Material材质深度解析,从基础到高级应用

445 阅读2分钟

一、材质核心概念

Three.js中的Material定义了3D物体表面的视觉特性,控制光线与物体表面的交互方式。作为几何体的"皮肤",材质通过颜色、纹理、金属度等属性实现真实感渲染。所有材质继承自基类THREE.Material,包含coloropacityside等通用属性。

二、材质分类与特性对比

1、 基础材质

材质类型光照支持性能消耗典型应用场景
MeshBasicMaterial最低UI元素/线框模型
PointsMaterial粒子系统
LineBasicMaterial路径绘制

示例代码

// 红色半透明立方体
const material = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  transparent: true,
  opacity: 0.5,
  wireframe: true
});

2、光照敏感材质

材质类型反射模型特性
MeshLambertMaterialLambert漫反射,无高光
MeshPhongMaterialBlinn-Phong支持镜面高光
MeshStandardMaterialPBR金属度/粗糙度控制

物理渲染(PBR)参数

  • metalness:金属质感强度(0-1)
  • roughness:表面粗糙度(0-1)
  • envMap:环境贴图

3、 特殊用途材质

材质类型功能特性
ShadowMaterial仅接收阴影
MeshDepthMaterial深度可视化(近白远黑)
MeshNormalMaterial法线方向可视化(RGB映射)

三、关键属性配置

1、颜色与透明度

// HSL颜色设置
material.color.setHSL(0.5, 1, 0.5); 
// 透明度配置
material.transparent = true;
material.opacity = 0.7;

2、纹理映射

贴图类型作用描述代码示例
map基础颜色纹理map: textureLoader.load()
normalMap法线贴图(表面凹凸)normalScale: new Vector2(1,1)
displacementMap位移贴图(几何形变)displacementScale: 0.1

3、高级光照属性

// Phong材质高光配置
const phongMat = new THREE.MeshPhongMaterial({
  specular: 0xffffff,  // 高光颜色
  shininess: 100       // 光泽度(0-100)
});

// 自发光设置
material.emissive.set(0xff0000); 
material.emissiveIntensity = 1.5;

四、自定义材质开发

1、ShaderMaterial

通过GLSL编写自定义着色器:

// 顶点着色器
varying vec3 vPosition;
void main() {
  vPosition = position;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

// 片元着色器
uniform vec3 color;
varying vec3 vPosition;
void main() {
  gl_FragColor = vec4(color * vPosition.z, 1.0);
}

2、材质动画

function animate() {
  requestAnimationFrame(animate);
  material.uniforms.time.value += 0.01;
  renderer.render(scene, camera);
}

五、性能优化策略

  1. 材质复用:相同材质的网格共享Material实例
  2. 纹理压缩:使用.basis.ktx2格式纹理
  3. LOD控制:根据距离切换材质精度
  4. 属性冻结
material.needsUpdate = false; // 停止材质更新

六、调试技巧

1、 法线可视化

const helper = new THREE.FaceNormalsHelper(mesh, 2);
scene.add(helper);

2、性能监控

import Stats from 'stats.js';
const stats = new Stats();
stats.showPanel(0); 
document.body.appendChild(stats.dom);

更多three.js、cesium.js开源案例,请移至gitee.com/giser2017/t…