目录
基础篇
顶点是什么
顶点几何体和geometry.attributes.position
顶点颜色geometry.attributes.color
顶点法向量geometry.attributes.normal
顶点复用geometry.index
基础篇
阅读顶点篇之前如果没有学习基础篇请先移步,方便了解学习环境:three.js基础篇
顶点是什么
基础篇中我们学会了网络模型mesh,网络模型基础包括了集合体Geometry和材质material。
其中几何体中我们可以很容易的使用BoxGeometry或者SphereGeometry创建柱状几何体或者球形几何体。
这些几何体其实都是通过顶点这个概念创建的,只不过它们在内部封装好了。
顶点几何体和geometry.attributes.position
面、线、点有效的几何体表达名为BufferGeometry
const geometry = new THREE.BufferGeometry()
1
当然它不像BoxGeometry或者SphereGeometry传递尺寸等参数就形成了几何体,它麻烦一些。
想要使用它我们得先借助js的内置对象Float32Array,32位浮点数对象生成一份矩阵数据。
const vertices = new Float32Array([ 0, 0, 0, 50, 0, 0, 0, 100, 0, 0, 0, 10, 0, 0, 100, 50, 0, 10, ]);
这份数据有什么用呢?
我们可以把它赋值给几何体属性值上的位置position。
当然还得使用到three能够搭配这份数据的方法BufferAttribute。
后面的3表示前面的数据3个为一组,一组3个数字分别代表一个点的xyz轴值,也就是这个模型总共包括了6个点。
geometry.attributes.position = new THREE.BufferAttribute(vertices, 3)
我们先不加材质,渲染一下试试啥样。
顺便复习一下基础篇生成网络模型再把模型加进场景的代码。
const mesh = new THREE.Mesh(geometry) scene.add(mesh)
会发现渲染出这几个点包围的图形,要明白最少三个点才可以包围出一个面。
我们如果旋转一下模型,往上转到底部,会发现这个面只有一个面能看见,背面看不见。
这是因为得在相应的材质上加上属性。
加上一个简单着色材质MeshBasicMaterial重新构建网络模型
注意这个材质不受光照影响,所以你现在可以看见颜色,等到后面介绍法向量时你可能会产生为啥现在可以看见光照的疑惑,这里已经先解释了。
const material = new THREE.MeshBasicMaterial({ color: 0x0000ff, //三角面颜色 side: THREE.DoubleSide //两面可见 }) const mesh = new THREE.Mesh(geometry,material) scene.add(mesh)
现在有颜色了而且可以看见背面。
顶点颜色geometry.attributes.color
创建几何体时我们使用到了geometry.attributes.position,它可以设置顶点的位置,同理我们还可以设置顶点的颜色。
同样也是以定点为单位设置,借助Float32Array。
同样是3个数一组,不过这次的3个数代表的是3原色,一组三原色构成一个点的颜色,取值范围0-1。
const colors = new Float32Array([ 1, 0, 0, //顶点1颜色 0, 1, 0, //顶点2颜色 0, 0, 1, //顶点3颜色 1, 1, 0, //顶点4颜色 0, 1, 1, //顶点5颜色 1, 0, 1, //顶点6颜色 ]); geometry.attributes.color = new THREE.BufferAttribute(colors, 3)
为了先理解顶点着色,我们还得改改材质和模型。
我们用点材质PointsMaterial代替简单材质,再使用Points模型代替mesh网络模型。
const material = new THREE.PointsMaterial({ vertexColors: THREE.VertexColors, size: 10.0 }) const points = new THREE.Points(geometry, material) scene.add(points)
可以看见六个点分别着上对应的颜色。
我们可以不换材质,换回网络模型。
const mesh = new THREE.Mesh(geometry, material) scene.add(mesh)
我们会发现当顶点颜色不同时,在顶点形成面的过程中会出现渐变,两个顶点形成线时会自动在中间自动插入过渡色,看起来就是渐变了。
顶点法向量geometry.attributes.normal
这个是法向量与光照有关,我们先把顶点着色改成全蓝。
之前用的MeshBasicMaterial不受光照影响看不出特别,随便换个MeshPhongMaterial材质好了。
去掉顶点着色,给材质颜色上个蓝色。
挪动一下下面两个点让两个面重合。
然后顺便加上环境光和点光源。
const vertices = new Float32Array([ 0, 0, 0, 50, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 100, 50, 0, 0, ]); geometry.attributes.position = new THREE.BufferAttribute(vertices, 3) const material = new THREE.MeshPhongMaterial({ color: 0x0000ff, side: THREE.DoubleSide }) const mesh = new THREE.Mesh(geometry, material) scene.add(mesh) //环境光 const ambient = new THREE.AmbientLight(0x444444); scene.add(ambient); // 点光源 const point = new THREE.PointLight(0xffffff); point.position.set(200, 400, 300); //点光源位置 scene.add(point); //点光源添加到场景中
会发现乌漆嘛黑,没有光照效果,颜色都看不见,我们明明加上了光源为什么没有效果呢。
因为用BufferGeometry的话,如果需要用普通材质,想要看到光照效果,必须设置顶点法向量。
设置时沿着三个点顺时针构成面的这面也就是我们看见的正面,让法向量从它们的反面穿过来,这样子正面将会作为光照到的外面。
听不懂就算了直接设置看效果,设置的属性换成normal,这次的三个数代表一个法向量,不知道法向量先学习数学。
const normals = new Float32Array([ 0, 0, 1, //顶点1法向量 0, 0, 1, //顶点2法向量 0, 0, 1, //顶点3法向量 0, 1, 0, //顶点4法向量 0, 1, 0, //顶点5法向量 0, 1, 0, //顶点6法向量 ]); geometry.attributes.normal = new THREE.BufferAttribute(normals, 3)
设置完就看见了,有棱角,有光照,我们分析一下法向量在哪里。
六个顶点的法向量是这样的,不明白原理知道怎么设置就行了。
顶点复用geometry.index
就在上面的例子,当两个三角形粘连的时候,每个三角形有两个顶点是重复了的。
因此我们没必要写出6个顶点,只要4个就可以表示同样的内容了。
把重复的顶点删除,再删除对应的法向量。
const vertices = new Float32Array([ 0, 0, 0, 50, 0, 0, 0, 100, 0, // 0, 0, 0, 0, 0, 100, // 50, 0, 0, ]); geometry.attributes.position = new THREE.BufferAttribute(vertices, 3) const normals = new Float32Array([ 0, 0, 1, //顶点1法向量 0, 0, 1, //顶点2法向量 0, 0, 1, //顶点3法向量 // 0, 1, 0, //顶点4法向量 0, 1, 0, //顶点5法向量 // 0, 1, 0, //顶点6法向量 ]); geometry.attributes.normal = new THREE.BufferAttribute(normals, 3)
然后就是使用我们的geometry.index来表明如何复用顶点。
根据顶点的数量选择类型数组Uint8Array、Uint16Array、Uint32Array。对于顶点索引而言选择整型类型数组,对于非索引的顶点数据,需要使用浮点类型数组Float32Array等。
这里的每个数字代表的是哪个顶点,我们上方设置了4个顶点,计数同数组从0开始,0、1、2三个顶点构成一个三角形,0,3,1三个顶点构成一个三角形。
const indexes = new Uint16Array([ 0, 1, 2, 0, 3, 1, ]) geometry.index = new THREE.BufferAttribute(indexes, 1)
能够显示出六个顶点要的效果,不过感觉连接处有一些粘连,所以可能还是得复用需要组合成一个形状的顶点才好,比如两个三角形拼成一个矩形,为了方便学习就就这么做了,可以自行尝试多加一个顶点在某个面上让三角形成为矩形。