【Three.js】BufferGeometry 基础讲解(position、normal、color、index)
1. BufferGeometry首先,在 three.js 中有THREE.Mesh 网格、THREE.Points 点、THREE.Line 线条等模型。其中:Mesh 网格模型创建的物体是由一个个小三角形组成,如下面各图。这些小三角形又是由三个点确定,需要三个确定的位置,即确定的 xyzPoints 模型创建的物体是由一个个点构成,每个点都有自己的位置,Points 相当于点的集合。Line
1. BufferGeometry
首先,在 three.js 中有THREE.Mesh 网格、THREE.Points 点、THREE.Line 线条等模型。其中:
-
Mesh 网格模型创建的物体是由一个个小三角形组成,如下面各图。这些小三角形又是由三个点确定,需要三个确定的位置,即确定的 xyz
-
Points 模型创建的物体是由一个个点构成,每个点都有自己的位置,Points 相当于点的集合。
-
Line 模型创建的物体是连续的线条,这些线可以理解为是按顺序把所有点连接起来。
不管是哪一种模型,它们都有一个共同点,就是都离不开点,每一个点都有确定的 x y z,BoxGeometry、SphereGeometry 帮我们封装了对这些点的操作,我们只需要告诉它们长宽高或者半径这些信息,它就会帮我创建一个默认的几何体。而 BufferGeometry 就是完全由我们自己去操作点信息的方法,我们可以通过它去设置每一个点的位置,即 position;每一个点的颜色,即 color;每一个点的法向量 normal 等。
2. position 设置点位置
1. 首先,我们将所有点的坐标存在一个类型化数组中,关于类型化数组的介绍可以查看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays。如下,每一行是一个点的x y z 值,我们按顺序存储每一个点的坐标,这里我们声明了六个点。
let positions = new Float32Array([
-10, 0, 0, // 0
10, 0, 0, // 1
0, 10, 0, // 2
0, 0, 5, // 3
0, 10, 5, // 4
0, 0, 15 // 5
]);
2. 定义好顶点数组后,我们将顶点设置到 BufferGeometry 中,代码如下。其中,THREE.BufferAttribute(positions, 3) 中第二个参数 3 指的是数组 positions 中每三个元素构成一个点,分别表示x y z 值。
geometry = new THREE.BufferGeometry();
geometry.attributes.position = new THREE.BufferAttribute(positions, 3);
3. 设置好后,此时如果我们构建网格模型,代码如下。此时,会自动以positions 数组中三行数据,即9个元素3个点,连接构成一个三角形。依次构成三角形,上面的六个点将构成两个三角形,效果如图:
let mesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
color: 0xff0000,
side: THREE.DoubleSide
})
);
scene.add(mesh);
4. 如果使用点模型构建,则会以每3个元素创建一个点,代码、效果如下:六个点直接显示出来。
let point = new THREE.Points(
geometry,
new THREE.PointsMaterial({
color: 0x00ff00,
size: 3
})
);
scene.add(point);
5. 如果使用线模型构建,则会按照点的顺序依次连接各个点,代码、效果如下:
let line = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({
color: 0x00ffff
})
);
scene.add(line);
3. 设置点颜色
1. 每一个点都可以设置颜色,颜色通过 rgb 值来设置,r g b 分别取 0-1之间的值。比如如下设置颜色,其中,每一行分别为一个点的颜色,每一行的三个元素分别是颜色的 rgb 值,下面设置了六个点的颜色。
let colors = new Float32Array([
1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 0,
0, 1, 1,
1, 0, 1
]);
2. 定义好颜色数组后,添加到 BufferGeometry 中,并且设置到材质中,举例创建一个Mesh模型如下:
geometry.addAttribute("color", new THREE.BufferAttribute(colors, 3));
let mesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors, // 该设置就是使用顶点设置颜色
side: THREE.DoubleSide
})
);
scene.add(mesh);
3. 可以看到网格、点、线设置顶点颜色后效果分别如下:
4. 设置点法向量
normal 的设置主要和光照相关,我们知道光照在物体的表面,由于光线与表面夹角角度的不一样,会导致亮度等也不一样。在 three.js 中,我们要知道一个物体的光照效果,需要知道物体表面每一个位置的法向方向,而 threejs 中的物体是由一个个点构成的,我们就需要知道每一个的法向量,这里的两个三角形法线方向分别是 z 轴和 x 轴。注意:法向量必须归一化,Vector3 中有方法可以直接调用。这里我们直接声明法向量数组:
let normals = new Float32Array([
0, 0, 1,
0, 0, 1,
0, 0, 1,
1, 0, 0,
1, 0, 0,
1, 0, 0
]);
geometry.addAttribute("normal", new THREE.BufferAttribute(normals, 3));
5. 设置 index
可以理解 index 为 positions 数组中的第n-1个点,如下每一行注释后面就是该点的 index 值。我们知道在 Mesh 模型中,threejs 直接按顺序没三个点一组创建一个三角形,index 就是为了帮助我们指定哪三个点构成一个三角形,并且这些点还可以重复使用。
let positions = new Float32Array([
-10, 0, 0, // 0
10, 0, 0, // 1
0, 10, 0, // 2
0, 0, 5, // 3
0, 10, 5, // 4
0, 0, 15 // 5
]);
如下,注意:这里用的是 Uint16Array,在这里,我们就可以通过6个点创建3个三角形,并且这些三角形的顶点都是我们自己指定的。而且,这里的 THREE.BufferAttribute(indexs, 1) 的第二个参数为 1 ,表示这里数组 indexs 中每一个元素表示一个点。
let indexs = new Uint16Array([
0, 1, 2,
3, 4, 5,
2, 4, 5
]);
geometry.index = new THREE.BufferAttribute(indexs, 1);
效果如下,三个三角形:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)