之前绘制的正方形都是基于三维空间绘制的一个2D图形,这里主要再多绘制5个正方形,来组成一个立方体的正方形。
定义立方体顶点位置
立体的正方形由6个面组成,每个面都有4个顶点,所以一共需要缓存24个顶点信息。在初始化缓存区的时候,需要先将24个点缓存起来。如下所示:
var vertices = [
// 前
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// 后
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// 上
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// 下
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// 右
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// 左
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
定义顶点颜色
为了区分正方体的每一个页,需要将每个面设置成不同的颜色,下面是为顶点设置颜色的代码,如下所示:
var colors = [
[1.0, 1.0, 1.0, 1.0], // 前:白色
[1.0, 0.0, 0.0, 1.0], // 后: 红色
[0.0, 1.0, 0.0, 1.0], // 上: 绿色
[0.0, 0.0, 1.0, 1.0], // 下: 蓝色
[1.0, 1.0, 0.0, 1.0], // 右: 黄色
[1.0, 0.0, 1.0, 1.0] // 左: 紫色
];
var generatedColors = [];
for (j=0; j<6; j++) {
var c = colors[j];
for (var i=0; i<4; i++) {
generatedColors = generatedColors.concat(c);
}
}
var cubeVerticesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(generatedColors), gl.STATIC_DRAW);
绘制面
设置好顶点和颜色后,就需要来绘制面了,每个面都是由两个三角形组成,首先需要创建三角形,如下所示:
var cubeVerticesIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // 前
4, 5, 6, 4, 6, 7, // 后
8, 9, 10, 8, 10, 11, // 上
12, 13, 14, 12, 14, 15, // 下
16, 17, 18, 16, 18, 19, // 右
20, 21, 22, 20, 22, 23 // 左
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
代码中的 cubeVertexIndices 数组声明每一个面都使用两个三角形来渲染。通过立方体顶点数组的索引指定每个三角形的顶点。那么这个立方体就是由12个三角形组成的了。
渲染立方体
绘制完面后,就需要来渲染立方体了。
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
立方体的每个面都由2个三角形组成,那就是每个面需要6个顶点,或者说总共36个顶点,尽管有许多重复的。然而,因为索引数组的每个元素都是简单的整数类型,所以每一帧动画需要传递给渲染程序的数据也不是很多。
创建好后的效果图如下所示: