Three.js 简介

几何体与材质

认识 Box、Sphere 等常用几何体,分清 Basic 与 Standard 两种材质的区别,学会给物体换形状和皮肤。

🎯 引言

上一篇我们用 BoxGeometry 画了一个立方体。Three.js 的场景就像一个剧团,能登台的演员远不止立方体。学完这篇文章,你能认识 4 种常用几何体,理解“材质决定物体看起来是什么料”,并分清 Basic 和 Standard 两种常用材质的区别。


🧱 物体的组成:几何体 + 材质

Three.js 里一个看得见的物体(Mesh)永远由两部分组成:

  • 几何体(Geometry):骨架,决定形状,是方是圆。
  • 材质(Material):皮肤,决定外观,什么颜色、受不受灯光影响。

打个比方:捏泥人时,几何体是你捏出的造型,材质是最后刷的那层釉。骨架不变,换层釉就从陶器变成瓷器。

const geometry = new THREE.BoxGeometry(1, 1, 1); // 骨架:立方体
const material = new THREE.MeshBasicMaterial({ color: 0x44aa88 }); // 皮肤:绿色
const cube = new THREE.Mesh(geometry, material); // 组合成物体

🧱 四种常用几何体

Three.js 内置了二十多种几何体,日常高频使用的是这 4 种:

几何体类名常用参数
立方体BoxGeometry宽、高、深
球体SphereGeometry半径
圆柱体CylinderGeometry顶部半径、底部半径、高度
圆锥体ConeGeometry底部半径、高度
const box = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material);
const sphere = new THREE.Mesh(new THREE.SphereGeometry(0.7), material);
const cylinder = new THREE.Mesh(new THREE.CylinderGeometry(0.5, 0.5, 1.2), material);
const cone = new THREE.Mesh(new THREE.ConeGeometry(0.6, 1.2), material);

把它们放进场景时,用 position.x 排开位置,避免挤在一起:

box.position.x = -3;
sphere.position.x = -1;
cylinder.position.x = 1;
cone.position.x = 3;

scene.add(box, sphere, cylinder, cone);

下面是这 4 个几何体的真实渲染效果(每个都转了个角度,方便看出立体感):

球体、圆柱体还能传“分段数”参数控制表面光滑度,比如 new THREE.SphereGeometry(0.7, 32, 16)。分段越多球面越光滑,但渲染开销也越大。默认值在大多数场景已经够用,觉得球面有棱角时再调大。

⚡ 两种常用材质:Basic 和 Standard

几何体决定形状,材质决定质感。高频使用的材质是这两种:

  • MeshBasicMaterial:基础材质,不受灯光影响,每个面都显示为均匀的颜色,看起来是“平”的。
  • MeshStandardMaterial:标准材质,会响应灯光,朝向光的面亮、背光的面暗,有真实的明暗立体感。上一篇的立方体用的就是它。

用同一个球体分别套用两种材质,代码只差一个类名:

// 左边:基础材质,不需要灯光,但缺少立体感
const left = new THREE.Mesh(
    new THREE.SphereGeometry(0.8),
    new THREE.MeshBasicMaterial({ color: 0x6699ff })
);
left.position.x = -1.5;

// 右边:标准材质,必须配合灯光才能显出立体感
const right = new THREE.Mesh(
    new THREE.SphereGeometry(0.8),
    new THREE.MeshStandardMaterial({ color: 0x6699ff })
);
right.position.x = 1.5;

// 标准材质需要光:环境光 + 平行光(下一篇详解)
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.5);
directionalLight.position.set(3, 5, 4);
scene.add(directionalLight);

scene.add(left, right);

下面是两种材质的真实渲染对比。注意左边 Basic 材质像一张扁平的圆形贴纸,右边 Standard 材质有明暗过渡,一眼就能看出是球:

用了 MeshStandardMaterial 却不加灯光,物体会黑乎乎一片甚至完全看不见。这不是 bug,是它“靠光才能显形”的特性。灯光的详细用法下一篇专门讲。

💡 调试利器:线框模式

所有材质都有一个 wireframe 属性,设为 true 后物体只显示骨架线框:

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

线框模式能清楚看到几何体由一个个三角形拼成,排查形状问题时非常好用。开发阶段打开看看,上线前记得关。


🧾 小节总结

  • 物体(Mesh)= 几何体(骨架形状)+ 材质(皮肤外观)。
  • 常用几何体:BoxGeometrySphereGeometryCylinderGeometryConeGeometry
  • MeshBasicMaterial 不受灯光影响,颜色均匀但缺少立体感。
  • MeshStandardMaterial 响应灯光、有明暗变化,必须配合灯光使用。
  • wireframe: true 只画骨架线框,是调试形状的好帮手。

❓ 知识问答

Q1:几何体的分段数(segments)是什么?

球、圆柱这类曲面几何体,实际是用很多小三角形拼出来的。分段数就是“拼多少块”,越多越圆滑、越耗性能。日常用默认值即可。

Q2:材质除了颜色还能设置什么,比如贴图片?

可以,这叫“纹理贴图”,通过 TextureLoader 加载图片后赋给材质的 map 属性。贴图属于进阶内容,掌握本课两种材质后再学很快。

Q3:一个几何体能配多个材质吗?

可以。给 Mesh 传材质数组,能让物体的不同面用不同材质,立方体的 6 个面各配一种颜色就是经典玩法。日常开发用得不多,了解即可。

Q4:Basic 材质既然没有立体感,还有什么用?

它开销小、渲染快,适合不需要光影的场景:纯色背景板、2D 风格的图形、调试用的占位物体等。


🧪 小练习

搭建一个“几何体小展台”:

  1. 在场景里并排放入球体、圆柱体、圆锥体三个物体。
  2. 统一使用 MeshStandardMaterial,颜色自选,并添加环境光和平行光。
  3. 把其中一个材质的 wireframe 设为 true,对比线框和实心的效果。
views/ShapeShow.vue
<template>
    <div ref="containerRef" class="container"></div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import * as THREE from 'three';

const containerRef = ref(null);

onMounted(() => {
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, 440 / 240, 0.1, 1000);
    camera.position.z = 5;

    // 请在这里编写代码

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(440, 240);
    containerRef.value.appendChild(renderer.domElement);
    renderer.render(scene, camera);
});
</script>

<style scoped>
.container {
    width: 440px;
    height: 240px;
}
</style>

🎉 恭喜你已经掌握几何体和材质啦!下一篇我们深入学习灯光,让场景从“看得见”变成“有氛围”。