首页 > 建站教程 > WebGL教程 Threejs教程 >  THREEJS BufferGeometry正文

THREEJS BufferGeometry

一、BufferGeometry

首先,在 three.js 中有THREE.Mesh 网格、THREE.Points 点、THREE.Line 线条等模型。其中:


Mesh 网格模型创建的物体是由一个个小三角形组成,如下面各图。这些小三角形又是由三个点确定,需要三个确定的位置,即确定的 xyz


1.png


Points 模型创建的物体是由一个个点构成,每个点都有自己的位置,Points 相当于点的集合。


Line 模型创建的物体是连续的线条,这些线可以理解为是按顺序把所有点连接起来。


不管是哪一种模型,它们都有一个共同点,就是都离不开点,每一个点都有确定的 x y z,BoxGeometry、SphereGeometry 帮我们封装了对这些点的操作,我们只需要告诉它们长宽高或者半径这些信息,它就会帮我创建一个默认的几何体。而 BufferGeometry 就是完全由我们自己去操作点信息的方法,我们可以通过它去设置每一个点的位置,即 position;每一个点的颜色,即 color;每一个点的法向量 normal 等。


二、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);


2.png


4. 如果使用点模型构建,则会以每3个元素创建一个点,代码、效果如下:六个点直接显示出来。


let point = new THREE.Points(
    geometry,
    new THREE.PointsMaterial({
        color: 0x00ff00,
        size: 3
    })
);
scene.add(point);


3.png


5. 如果使用线模型构建,则会按照点的顺序依次连接各个点,代码、效果如下:


let line = new THREE.Line(
    geometry,
    new THREE.LineBasicMaterial({
        color: 0x00ffff
    })
);
scene.add(line);


4.png


三、设置点颜色

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. 可以看到网格、点、线设置顶点颜色后效果分别如下:


5.png

6.png


四、设置点法向量

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));


五、设置 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);


效果如下,三个三角形:


7.png