以构建一个魔方为例
<div id="cube"></div>
全局变量
camera: null,
scene: null,
renderer: null,
controls: null,
faceA: [1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0],
faceB: [0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0],
faceC: [0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1],
faceD: [1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0],
faceE: [0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1],
faceF: [1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1],
faceG: [1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1],
创建渲染器等内容
this.scene=new THREE.Scene();
//环境光
const ambient = new THREE.AmbientLight(0xffffff);
//环境光添加到场景中
this.scene.add(ambient);
const width = window.innerWidth;
// 窗口高度
const height = window.innerHeight;
// 创建相机对象
this.camera = new THREE.PerspectiveCamera( 45, width / height, 0.1, 1000 );
// 设置相机的位置
this.camera.position.set(0,0,300);
// 设置相机的方向(指向场景的方向)
this.camera.lookAt(this.scene.position);
/**
* 创建渲染器的对象
*/
this.renderer = new THREE.WebGLRenderer({antialias: true,logarithmicDepthBuffer:true});
// 设置渲染区域的尺寸
this.renderer.setSize(width,height);
// 设置背景颜色
this.renderer.setClearColor(0x424142,1);
this.renderer.shadowMap.enabled = true
// 指定元素中插入canvas对象
const webglBox = document.getElementById("cube");
webglBox.appendChild(this.renderer.domElement);
正方体顶点相对位置(基于自身坐标系的位置)
const vertices=new Float32Array([
-10,10,10,10,10,10,10,-10,10,
10,-10,10,-10,-10,10,-10,10,10, // 正面
-10,10,-10,10,10,-10,10,-10,-10,
10,-10,-10,-10,-10,-10,-10,10,-10, // 背面
10,10,10,10,10,-10,10,-10,-10,
10,-10,-10,10,-10,10,10,10,10, //右面
-10,10,10,-10,10,-10,-10,-10,-10,
-10,-10,-10,-10,-10,10,-10,10,10, //左面
-10,10,10,10,10,10,10,10,-10,
10,10,-10,-10,10,-10,-10,10,10, // 顶面
-10,-10,10,10,-10,10,10,-10,-10,
10,-10,-10,-10,-10,-10,-10,-10,10 //地面
])
构建魔方
for (let i = -1; i < 2; i++) {
for (let j = -1; j < 2; j++) {
for (let k = -1; k < 2; k++) {
// 创建几何体
const geometry=new THREE.BufferGeometry();
geometry.attributes.position=new THREE.BufferAttribute(vertices, 3);
let colorsArr1=[],colorsArr2=[],colorsArr3=[];
// 为不同位置的几何体的各个面赋予不同的颜色
switch (i) {
case -1: {
colorsArr1 = [...this.faceG, ...this.faceC];
break;
}
case 0: {
colorsArr1 = [...this.faceG, ...this.faceG];
break;
}
case 1: {
colorsArr1 = [...this.faceA, ...this.faceG];
break;
}
}
switch (k) {
case -1: {
colorsArr2 = [...this.faceG, ...this.faceD];
break;
}
case 0: {
colorsArr2 = [...this.faceG, ...this.faceG];
break;
}
case 1: {
colorsArr2 = [...this.faceB, ...this.faceG];
break;
}
}
switch (j) {
case -1: {
colorsArr3 = [...this.faceG, ...this.faceF];
break;
}
case 0: {
colorsArr3 = [...this.faceG, ...this.faceG];
break;
}
case 1: {
colorsArr3 = [...this.faceE, ...this.faceG];
break;
}
}
const colorsArr=[...colorsArr1,...colorsArr2,...colorsArr3];
const colors=new Float32Array(colorsArr);
geometry.attributes.color=new THREE.BufferAttribute(colors,3);
// 创建材质
const material= new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors, //以顶点颜色为准
side: THREE.DoubleSide, //两面可见
});
const mesh=new THREE.Mesh(geometry,material);
mesh.name=i+""+j+""+k
// 正方体的位置(基于世界坐标系)
mesh.position.set(k*23,j*23,i*23);
this.scene.add(mesh);
}
}
}
this.renderer.render(this.scene,this.camera);
重点:
使用BufferGeometry自己手动写入顶点位置信息构建物体
为同一个面的每一个顶点赋予相同的颜色
使用MeshBasicMaterial创建材质,并声明以顶点颜色为准,且两面可见(保证在某些角度观察正方体的时候不会出现透视现象)