学习Three.js--网格模型
前置核心说明
上文说明了 「场景(Scene)、相机(Camera)、渲染器(Renderer)」三大核心、几何体(Geometry)、材质(Material) 相关知识,而 「网格模型(Mesh)」就是衔接「几何体」和「材质」的核心桥梁,是 Three.js 中实现可视化3D物体的最终载体。
核心关系
几何体(Geometry) → 物体的「骨架/形状」
材质(Material) → 物体的「皮肤/外观」
网格模型(Mesh) → 将「骨架+皮肤」绑定为一个完整的、可渲染的3D实体对象
所有能在 Three.js 场景中看到的实体3D物体,本质都是各类「网格/渲染对象」;
所有网格对象创建后,都通过 scene.add(网格对象) 方法添加到场景中才能被渲染;
单位遵循 Three.js 右手坐标系:X轴右、Y轴上、Z轴外,角度单位均为「弧度」。
一、什么是 THREE.Mesh 核心网格模型
1.1 概念与核心作用
THREE.Mesh 是 Three.js 中 最基础、最核心、使用率99%的网格渲染类,也是所有立体实体模型的核心载体。
- 作用:接收「几何体」和「材质」两个核心参数,将二者封装为一个具备形状+外观的完整3D对象;
- 特性:
THREE.Mesh渲染的是带面、带体积的实心几何体,支持光照、阴影、纹理、透明度等所有材质特性; - 适用场景:所有立体3D实体 → 立方体、球体、圆柱、自定义模型等,都是通过
THREE.Mesh实现渲染。
1.2 标准创建语法 & 完整参数
基础语法
// 语法:new THREE.Mesh(几何体, 材质)
const mesh = new THREE.Mesh( geometry, material );
scene.add(mesh); // 添加到场景才能渲染
参数详细说明
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
geometry | THREE.Geometry / THREE.BufferGeometry | 是 | 几何体对象,定义网格的形状/结构(如BoxGeometry、SphereGeometry) |
material | THREE.Material 任意子类 | 是 | 材质对象,定义网格的外观(如MeshStandardMaterial、MeshBasicMaterial) |
扩展语法(材质传数组,一个几何体绑定多个材质)
// 一个几何体的不同面,绑定不同材质,材质数组的长度要与几何体的面数匹配
const mesh = new THREE.Mesh( geometry, [material1, material2, material3] );
1.3 核心注意事项
- 材质/几何体复用:同一个几何体/材质可以被多个
Mesh复用,比如100个立方体用同一个几何体+材质,仅创建1份即可,极大节省内存,优化性能; - 几何体类型兼容:
THREE.Mesh仅支持「面几何体」(有体积、有面的几何体),不支持线、点类几何体; - 版本提示:Three.js
r125+版本后,推荐使用 BufferGeometry 替代旧的 Geometry,前者性能更高,是官方主推的几何体类型,二者用法一致。
二、THREE.Mesh 核心公共属性 & 方法
THREE.Mesh 继承自 THREE.Object3D,拥有所有3D对象通用的核心属性和方法,这些是你操控3D物体的核心API,所有网格/渲染对象都共用,必学必记,无例外!
所有属性支持「创建后动态修改」,修改后立即生效,无需重新创建Mesh。
2.1 三大核心变换属性(位置、旋转、缩放,最常用TOP3)
① 位置属性 position → 控制物体在场景中的坐标
// 类型:THREE.Vector3 对象,默认值 (0, 0, 0) 场景原点
mesh.position.x = 2; // X轴向右移动2个单位
mesh.position.y = -1; // Y轴向下移动1个单位
mesh.position.z = 3; // Z轴向外移动3个单位
// 批量设置:x, y, z
mesh.position.set(2, -1, 3);
② 旋转属性 rotation → 控制物体的旋转角度
// 类型:THREE.Euler 对象,默认值 (0, 0, 0),单位是「弧度」不是角度!
mesh.rotation.x = Math.PI / 2; // 绕X轴旋转90°
mesh.rotation.y = Math.PI; // 绕Y轴旋转180°
mesh.rotation.z = Math.PI / 4; // 绕Z轴旋转45°
// 批量设置:x, y, z 弧度值
mesh.rotation.set(Math.PI/2, Math.PI, Math.PI/4);
// 角度转弧度小技巧:角度值 * Math.PI / 180
mesh.rotation.y = 45 * Math.PI / 180; // 绕Y轴旋转45°
③ 缩放属性 scale → 控制物体的大小缩放
// 类型:THREE.Vector3 对象,默认值 (1, 1, 1) 原始尺寸
mesh.scale.x = 2; // X轴放大2倍
mesh.scale.y = 0.5; // Y轴缩小为原来的0.5倍
// 批量设置:等比缩放/非等比缩放
mesh.scale.set(2, 0.5, 1); // X放大2倍,Y缩小0.5倍,Z不变
mesh.scale.set(3,3,3); // 整体等比放大3倍
2.2 高频基础属性
mesh.visible = true; // 布尔值,默认true,是否显示该物体;false则隐藏,不参与渲染
mesh.name = "cube"; // 字符串,给物体命名,可通过 scene.getObjectByName("cube") 获取该物体
mesh.userData = {id:1, type:"cube"}; // 自定义数据,存储业务相关信息,不影响渲染
mesh.matrixAutoUpdate = true; // 布尔值,默认true,自动更新变换矩阵;手动控制矩阵时设为false
2.3 光影相关核心属性(实现阴影必备)
mesh.castShadow = true; // 布尔值,默认false,该物体是否「投射阴影」到其他物体上
mesh.receiveShadow = true; // 布尔值,默认false,该物体是否「接收」其他物体投射的阴影
注意:开启阴影后,还需要开启「光源的阴影投射」+「渲染器的阴影支持」才能生效。
2.4 核心常用方法
// 1. 让物体始终朝向某个目标点/物体
mesh.lookAt(new THREE.Vector3(0,0,0)); // 朝向场景原点
mesh.lookAt(camera.position); // 朝向相机位置
// 2. 给物体添加子物体(父子层级关系)
const childMesh = new THREE.Mesh(geo, mat);
mesh.add(childMesh); // childMesh成为mesh的子物体,继承父物体的位置/旋转/缩放
// 3. 移除子物体
mesh.remove(childMesh);
// 4. 克隆当前物体(深拷贝,包含几何体、材质、所有属性)
const meshClone = mesh.clone();
scene.add(meshClone);
// 5. 清除物体的所有变换(位置归零、旋转归零、缩放还原)
mesh.resetMatrix();
三、Three.js 中「所有网格/渲染对象」分类大全(完整8类,含参数+用途)
Three.js 提供的所有可视化渲染对象 —— THREE.Mesh 只是「立体实体」的核心,Three.js 为了满足不同的可视化需求,提供了8类专用的网格/渲染对象,全部继承自 THREE.Object3D,共用上述所有公共属性和方法,只是渲染形态、适用场景、创建参数不同。
核心分类原则
所有渲染对象按「渲染形态」分为四大类:实体类、线类、点类、精灵类,以下按「使用率从高到低」排序,全部整理了 创建语法、完整参数、核心特点、适用场景
第一类:实体类渲染对象(核心,立体有体积,共2个)
1. THREE.Mesh(上文详解,使用率 99%)
- 核心:渲染实心立体几何体,带面、带体积,支持所有材质;
- 适用:所有3D实体模型(立方体、球体、圆柱、自定义模型);
- 创建:
new THREE.Mesh(geometry, material)。
2. THREE.SkinnedMesh(骨骼蒙皮网格,进阶)
- 核心:
THREE.Mesh的子类,支持骨骼绑定+蒙皮动画,可以让模型实现关节弯曲、人物行走等骨骼动画; - 适用:人物模型、动物模型、有骨骼动画的3D角色;
- 创建语法 & 参数:
// 语法:new THREE.SkinnedMesh(几何体, 材质, 骨骼数组(可选)) const skinnedMesh = new THREE.SkinnedMesh(geometry, material, bones); - 特点:比普通Mesh多了骨骼相关的属性和方法,是实现3D角色动画的核心。
第二类:线类渲染对象(纯线条,无面无体积,共3个)
所有线类对象,必须搭配「线材质」:
LineBasicMaterial(实线) /LineDashedMaterial(虚线),不能使用Mesh系列材质! 核心特点:只渲染几何体的「棱边/顶点连线」,无面、无体积,性能极高,适合绘制轮廓、辅助线、轨迹线等。
1. THREE.Line(连续线条,使用率最高)
// 语法:new THREE.Line(几何体, 材质)
// 几何体:必须是 BufferGeometry,顶点按顺序连成「一条连续的折线」
const lineGeometry = new THREE.BufferGeometry().setFromPoints([
new THREE.Vector3(0,0,0),
new THREE.Vector3(2,0,0),
new THREE.Vector3(2,2,0)
]);
const lineMaterial = new THREE.LineBasicMaterial({color:0xff0000});
const line = new THREE.Line(lineGeometry, lineMaterial);
scene.add(line);
- 特点:顶点按传入顺序首尾相连成连续线条,最后一个顶点不闭合到起点;
- 适用:折线、轨迹线、连接线、电路图等。
2. THREE.LineSegments(分段线条)
// 语法:new THREE.LineSegments(几何体, 材质)
// 特点:顶点按「两两一组」渲染成独立的线段,组与组之间不连接
const line = new THREE.LineSegments(geometry, material);
- 适用:网格辅助线、坐标轴、虚线框、多段独立线条等。
3. THREE.LineLoop(闭合线条)
// 语法:new THREE.LineLoop(几何体, 材质)
// 特点:顶点按顺序连成连续线条,「最后一个顶点会闭合到第一个顶点」,形成封闭图形
const line = new THREE.LineLoop(geometry, material);
- 适用:圆形轮廓、正方形边框、封闭轨迹线等。
线类必看注意点:使用
LineDashedMaterial(虚线材质) 时,必须给几何体执行geometry.computeLineDistances(),否则虚线不生效!
第三类:点/粒子类渲染对象(纯点,共1个)
THREE.Points(粒子/点云模型)
// 语法:new THREE.Points(几何体, 材质)
// 核心:必须搭配「点材质」PointsMaterial,不能使用其他材质
const pointsArr = [];
const count = 1000;
for (let i = 0; i < count; i++) {
const x = (Math.random() - 0.5) * 10; // -5 ~ +5
const y = (Math.random() - 0.5) * 10;
const z = (Math.random() - 0.5) * 10;
pointsArr.push(new THREE.Vector3(x, y, z));
}
const pointsGeometry = new THREE.BufferGeometry().setFromPoints(pointsArr); // pointsArr是顶点数组
const pointsMaterial = new THREE.PointsMaterial({color:0xffffff, size:2});
const points = new THREE.Points(pointsGeometry, pointsMaterial);
scene.add(points);
- 核心特点:渲染几何体的每个顶点为一个独立的点/粒子,无面、无线条,仅显示点;
- 材质专属:只能用
THREE.PointsMaterial,支持粒子大小、颜色、透明度、纹理贴图; - 适用场景:粒子特效(星空、雪花、雨滴、烟雾、火焰)、点云模型、数据可视化散点图等。
第四类:精灵类渲染对象(2D平面,始终朝相机,共2个)
1. THREE.Sprite(精灵模型)
// 语法:new THREE.Sprite(材质) → 无需几何体!
const spriteMaterial = new THREE.SpriteMaterial({color:0xff0000, transparent:true});
const sprite = new THREE.Sprite(spriteMaterial);
scene.add(sprite);
- 核心特点:无需几何体,本质是一个「无限薄的2D正方形平面」,无论相机如何旋转,始终正面朝向相机;
- 材质专属:必须搭配
THREE.SpriteMaterial精灵材质; - 大小控制:通过
sprite.scale.set(width, height, 1)控制尺寸; - 适用场景:3D场景中的2D元素(图标、血条、标签、子弹、火焰粒子、雪花)。
2. THREE.SpriteGroup(精灵组,进阶)
- 核心:批量渲染多个Sprite,性能极高,适合创建大量精灵(如10000个雪花、雨滴);
- 语法:
new THREE.SpriteGroup(material, {size:1000}); - 适用:大规模粒子特效、海量精灵渲染。
四、补充:特殊「网格相关」知识点
4.1 关于「BufferGeometry 优先使用」的说明
Three.js 中有两种几何体:Geometry(旧版) 和 BufferGeometry(新版),二者都能传给Mesh/Line/Points,但:
- 推荐:所有场景优先使用 BufferGeometry,它是官方主推的几何体类型;
- 优势:
BufferGeometry对GPU更友好,内存占用更少,渲染性能更高,支持所有新特性; - 兼容:所有网格对象对两种几何体的支持完全一致,用法无区别,只是创建方式不同。
4.2 网格模型的性能优化核心技巧
- 复用几何体和材质:同一个几何体/材质,尽量给多个网格对象复用,减少内存占用;
- 减少分段数:几何体的分段数越高,顶点越多,渲染越慢,够用即可(如球体32段足够平滑);
- 批量渲染:大量相同的简单物体,使用
InstancedMesh(实例化网格)替代多个Mesh,性能提升百倍; - 隐藏不可见物体:对屏幕外的物体设置
visible=false,减少渲染计算; - 减少阴影开启:阴影渲染性能开销大,非必要场景关闭
castShadow/receiveShadow。
4.3 易混淆概念区分
- 误区:
THREE.Mesh是唯一的网格模型 → 正确:Mesh只是「实体网格」,还有线、点、精灵等专用渲染对象; - 误区:线类对象可以用Mesh材质 → 正确:线类必须用线材质,点类必须用点材质,精灵必须用精灵材质,材质和渲染对象是一一对应的;
- 误区:Sprite需要几何体 → 正确:Sprite无需几何体,是自带2D平面的渲染对象。
五、完整的「Mesh创建+使用」示例代码
// 官网地址
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r132/build/three.module.js'
// 1. 创建三大核心
//场景
const scene = new THREE.Scene();
//透视相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
//相机默认创建在场景的**坐标原点 (0,0,0)**,与场景中心重合,此时会和几何体重叠导致看不到内容,**必须手动调整相机位置**,最常用的就是调整Z轴让相机「后退」:
// 相机沿Z轴向后移动5个单位,即可看到场景中心的物体
camera.position.z = 5;
//渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染画布的尺寸(与浏览器窗口一致,满屏显示)
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器生成的canvas画布,添加到HTML页面中
document.body.appendChild(renderer.domElement);
// 2. 创建几何体+材质
const geometry = new THREE.BoxGeometry(2,2,2); // 立方体几何体
const material = new THREE.MeshStandardMaterial({color:0x00ff00, roughness:0.5, metalness:0.2}); // PBR材质
// 3. 创建核心网格模型Mesh
const cubeMesh = new THREE.Mesh(geometry, material);
// 设置Mesh属性
cubeMesh.position.set(0, 0, 0); // 位置
cubeMesh.rotation.set(Math.PI/4, Math.PI/4, 0); // 旋转
cubeMesh.scale.set(1,1,1); // 缩放
cubeMesh.castShadow = true; // 投射阴影
cubeMesh.name = "cube"; // 命名
// 4. 添加到场景
scene.add(cubeMesh);
// 5. 添加光源(PBR材质必须加光源)
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5,5,5);
dirLight.castShadow = true;
scene.add(ambientLight, dirLight);
// 6. 动画循环
function animate() {
requestAnimationFrame(animate);
cubeMesh.rotation.x += 0.01;
cubeMesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
核心知识总结
- 核心关系:几何体(形状)+材质(外观) → Mesh(实体对象),Mesh是3D实体的最终载体;
- 网格体系:Three.js的可视化对象分4类 → 实体(Mesh/SkinnedMesh)、线(Line/LineSegments)、点(Points)、精灵(Sprite);
- 三大变换:所有网格对象共用
position(位置)、rotation(旋转)、scale(缩放),是操控物体的核心; - 材质匹配:实体用Mesh材质,线用线材质,点用点材质,精灵用精灵材质,一一对应;
- 性能优先:优先用BufferGeometry,复用几何体/材质,减少分段数,提升渲染效率。