2、基础材质(MeshBasicMaterial):属性详解

好,咱们今天聊聊 Three.js 里最基础、也最容易被轻视的材质——MeshBasicMaterial

说实话,我刚学 Three.js 那会儿,觉得这玩意儿太简单了,不就是个纯色填充吗?后来做项目多了才发现,越是基础的东西,用好了反而能出奇效。

2.1 核心特点:不受光照影响

这是 MeshBasicMaterial 最根本的特性。你想想看,场景里加再多灯光,点光源、平行光、环境光……它统统无视。

为什么会有这种材质?

因为不是所有物体都需要光照计算。比如 UI 元素、背景天空盒、或者一些纯色装饰物。你给它们加光照,反而显得多余,还浪费性能。

关键点:MeshBasicMaterial 直接使用颜色值或纹理颜色,不参与任何光照计算。它的颜色就是最终显示的颜色。

我记得有一次做移动端项目,场景里有一堆小图标。如果用标准材质,每个图标都得参与光照计算,帧率直接掉到 30 以下。换成 MeshBasicMaterial 后,帧率瞬间回到 60。嗯,这就是它的价值。

2.2 属性详解

2.2.1 color —— 颜色控制

最常用的属性,没有之一。你可以用十六进制、颜色字符串、或者 THREE.Color 对象来设置。

// 三种方式,效果一样
const material1 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshBasicMaterial({ color: 'red' });
const material3 = new THREE.MeshBasicMaterial({ color: new THREE.Color('red') });

我个人习惯用十六进制,因为直观,而且从设计稿里复制颜色值也方便。

小技巧:如果你想让材质半透明,记得同时设置 transparent: trueopacity 属性。光设 opacity 是没用的。

2.2.2 map —— 纹理贴图

给材质贴上一张图片,这就是纹理映射。用法很简单:

const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('path/to/texture.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture });

这里有个坑,我曾经踩过:纹理加载是异步的。如果你在纹理还没加载完时就渲染,物体会显示为黑色。解决办法是用 onLoad 回调,或者干脆用 LoadingManager 统一管理。

注意:纹理图片的尺寸最好是 2 的幂次方(如 512x512、1024x1024),否则在某些设备上会出现奇怪的拉伸或性能问题。

2.2.3 wireframe —— 线框模式

这个属性特别适合调试。设成 true 后,物体会显示为线框结构,方便你观察几何体的顶点和三角面分布。

const material = new THREE.MeshBasicMaterial({ 
  color: 0x00ff00,
  wireframe: true 
});

我刚开始学 Three.js 时,经常用线框模式来理解复杂几何体的结构。比如一个球体,线框模式下你能清楚看到经纬线的分布方式。

不过要注意,线框模式下颜色属性依然有效,但纹理贴图会被忽略。

2.2.4 其他常用属性

属性名 类型 说明
transparent Boolean 是否启用透明度,默认 false
opacity Number 透明度值,0~1,需配合 transparent: true
side THREE.Side 渲染哪一面:THREE.FrontSide(默认)、BackSide、DoubleSide
visible Boolean 是否可见,默认 true

2.3 适用场景

聊完属性,咱们说说这材质到底用在哪儿。

2.3.1 UI 元素

游戏里的血条、按钮、提示文字……这些都不需要光照。用 MeshBasicMaterial 渲染,性能好,颜色也准确。

我之前做过一个数据可视化项目,所有标签和图标都用这个材质。因为 UI 元素需要颜色稳定,不受场景灯光影响。你想想看,如果按钮颜色随着灯光变化,用户会疯掉的。

2.3.2 天空盒

天空盒说白了就是一个巨大的盒子,把场景包在里面。它不需要光照,因为天空本身就是光源。

// 天空盒材质示例
const skyMaterial = new THREE.MeshBasicMaterial({
  map: skyTexture,
  side: THREE.BackSide  // 从内部看
});

这里有个细节:天空盒的材质要设置 side: THREE.BackSide,因为相机在盒子内部,我们需要看到盒子的内表面。

2.3.3 调试与预览

开发阶段,用 MeshBasicMaterial 快速搭建场景原型,等布局确定后再换成标准材质。这样能省下不少调试时间。

2.3.4 纯色装饰物

比如地面网格、辅助线、或者一些抽象几何体。这些物体不需要真实感渲染,用基础材质就够了。

2.4 避坑指南

最后分享几个我踩过的坑:

  • 纹理不显示? 检查纹理路径是否正确,以及图片是否跨域(如果从外部加载)。
  • 颜色不对? 确认没有误设 emissive 属性——那是标准材质才有的。
  • 性能问题? 如果场景里大量使用 MeshBasicMaterial,可以考虑合并几何体,减少 draw call。

我的习惯:每个新项目开始前,我都会先用 MeshBasicMaterial 搭一个快速原型。等所有物体位置、大小都调好了,再逐个替换成更复杂的材质。这样能避免在调试光照时还要反复调整位置,效率高很多。

好了,关于 MeshBasicMaterial 就聊这么多。下一章咱们会讲标准材质,那才是真正开始玩光照的地方。