3、几何体与材质:内置几何体与基础材质
好,咱们进入第三章。这一章我打算聊聊 Three.js 里最基础、也最常用的两个概念——几何体和材质。
说白了,几何体就是物体的「骨架」,材质就是物体的「皮肤」。你想想看,一个 3D 场景里,不管多复杂的模型,拆到最底层,都是由一个个几何体拼起来的。而材质决定了这个几何体看起来像什么——是金属、塑料、还是木头?
我个人习惯,每次开始一个新项目,都会先用内置几何体搭个「草稿」。这样能快速验证光照、相机位置这些基础设置。等一切就绪了,再替换成精细模型。这个习惯帮我省了不少时间。
3.1 内置几何体:开箱即用的形状
Three.js 内置了好几种几何体,最常用的就是 Box、Sphere、Cylinder 这三个。我刚开始学的时候,觉得它们太简单了,后来才发现,很多复杂场景其实都是这些基础形状的组合。
3.1.1 BoxGeometry(立方体)
这个最常用,也最好理解。你传三个参数进去,它就能生成一个长方体。
const geometry = new THREE.BoxGeometry(2, 1, 3);
// 宽度 2,高度 1,深度 3
嗯,这里要注意:参数顺序是 width、height、depth。我见过不少新手把顺序搞反,结果模型变形了还找不到原因。
new THREE.BoxGeometry(1, 1, 1)。
3.1.2 SphereGeometry(球体)
球体稍微复杂一点,因为它涉及到「分段数」的概念。
const geometry = new THREE.SphereGeometry(1, 32, 16);
// 半径 1,宽度分段 32,高度分段 16
为什么要有分段数?因为计算机没法画真正的圆,它只能用多边形去「模拟」圆。分段数越高,球体越光滑,但性能开销也越大。
我曾经在做一个移动端项目时,把球体的分段数设成了 128,结果在低端手机上直接卡成幻灯片。后来我改成了 24 和 12,肉眼几乎看不出区别,但帧率从 20 飙到了 60。所以,别盲目追求高分段,够用就行。
3.1.3 CylinderGeometry(圆柱体)
圆柱体也挺有意思,它不仅能做圆柱,还能做圆锥、甚至多棱柱。
const geometry = new THREE.CylinderGeometry(1, 1, 2, 32);
// 顶部半径 1,底部半径 1,高度 2,径向分段 32
如果你把顶部半径设为 0,它就变成了一个圆锥。如果你把径向分段设为 6,它就变成了一个六棱柱。这个灵活性在实际项目中非常有用。
| 几何体 | 常用参数 | 典型应用场景 |
|---|---|---|
| BoxGeometry | width, height, depth | 建筑、箱子、墙壁 |
| SphereGeometry | radius, widthSegments, heightSegments | 星球、球体装饰、碰撞体 |
| CylinderGeometry | radiusTop, radiusBottom, height, radialSegments | 柱子、管道、圆锥 |
3.2 基础材质:给几何体穿上衣服
几何体搭好了,接下来就是材质。Three.js 提供了好几种材质,但最基础、最常用的就两个:MeshBasicMaterial 和 MeshStandardMaterial。
3.2.1 MeshBasicMaterial(基础材质)
这个材质最简单,它不受光照影响。你给它什么颜色,它就显示什么颜色。
const material = new THREE.MeshBasicMaterial({
color: 0xff0000, // 红色
wireframe: false // 是否显示线框
});
说实话,这个材质在实际项目中用得不多,因为它没有立体感。但它非常适合做调试——比如你想快速看看几何体的形状对不对,或者做 UI 元素、辅助线之类的东西。
3.2.2 MeshStandardMaterial(标准材质)
这个才是主力。它基于物理渲染(PBR),能模拟真实世界的光照效果。
const material = new THREE.MeshStandardMaterial({
color: 0x00ff00,
roughness: 0.5, // 粗糙度,0 最光滑,1 最粗糙
metalness: 0.3 // 金属感,0 非金属,1 纯金属
});
我个人习惯,roughness 和 metalness 这两个参数一定要调。很多人只改 color,结果模型看起来像塑料玩具。你试试 roughness 设成 0.2、metalness 设成 0.8,立马就有金属质感了。
我记得有一次做产品展示,客户说模型看起来「太假了」。我调了半天光照都没用,最后发现是 roughness 设得太高了,表面太粗糙,没有反光。改成 0.3 之后,效果立竿见影。
3.3 颜色与纹理:让材质活起来
光有纯色材质还不够,真实世界的东西都是有纹理的——木头的纹路、石头的颗粒、布料的编织。
3.3.1 颜色设置
Three.js 支持多种颜色表示方式:
// 十六进制
material.color.setHex(0xff6600);
// RGB 字符串
material.color.setStyle('#ff6600');
// 颜色名称
material.color.set('orange');
我个人推荐用十六进制,因为它最精确,也最容易从设计稿里复制。
3.3.2 纹理贴图
纹理才是让材质「活起来」的关键。你需要用 TextureLoader 来加载图片。
const loader = new THREE.TextureLoader();
const texture = loader.load('path/to/texture.jpg');
const material = new THREE.MeshStandardMaterial({
map: texture, // 颜色贴图
roughnessMap: texture, // 粗糙度贴图(可选)
normalMap: texture // 法线贴图(可选)
});
嗯,这里有个坑:纹理加载是异步的。如果你在加载完成之前就渲染场景,可能会看到一片灰色。我建议用 loader.load 的回调函数,等纹理加载完了再添加到场景里。
- 几何体定义形状,材质定义外观
- MeshBasicMaterial 不受光照,适合调试
- MeshStandardMaterial 是主力,记得调 roughness 和 metalness
- 纹理让材质更真实,但要注意加载时机
好了,这一章的内容就这些。下一章我们会把这些几何体和材质组合起来,真正搭建一个完整的 3D 场景。到时候我会分享一些我在实际项目中踩过的坑,保证有用。