在上一章里我们成功地用 WebGL 在画布上绘制出了一个三角形。这一章,我们继续拓展上一章的内容,绘制一些不一样的东西。
本章主要围绕以下两个知识点展开:1. 高效绘制多个三角形;2. 绘制不同颜色的三角形。
高效绘制多个三角形
看到这个标题,肯定很多同学会想:画一个三角形我会了,多画几个还不容易?
// 首先,改顶点,绘制两个三角形,让它们构成一个矩形
const positions = [
0, 0,
0, 0.5,
0.7, 0,
0, 0.5,
0.7, 0.5,
0.7, 0
];
// 其次,绘制的时候,增加绘制的顶点数量
gl.drawArrays(gl.TRIANGLES, 0, 6);
结果最终绘制出来是这样的:
这样绘制实际上是没有问题的,但应该会有细心的朋友发现,有两个顶点数据重复提交了,原本用 4 个顶点就能绘制矩形,现在要用 6 个,白白多产生了 50% 的开销!如果场景很庞大,这个问题就会越来越严重。因此,可以采用的解决方案是:提供最优顶点,之后只需要指定绘制的顺序就可以了,我们把指定绘制顺序的方法称之为顶点索引。之前我们采用“gl.drawArrays” 的方式直接绘制顶点,接下来,我们需要使用顶点索引的方法 "gl.drawElements" 来绘制。改造一下上面的内容:
// 只提供四个顶点
const positions = [
0, 0,
0, 0.5,
0.7, 0,
0.7, 0.5,
];
// 同时提供索引数组,从 positions 中取顶点构造顺序
// 索引从数组的 0 开始
const indices = [
0, 1, 2, // 第一个三角形
2, 1, 3 // 第二个三角形
];
// 对 “步骤二:顶点着色器” 顶点缓冲和绑定这里进行修改
// 上传顶点缓冲
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
// 上传索引缓冲
const indexBuffer = gl.createBuffer();
// ELEMENT_ARRAY_BUFFER 是专门用来绑定索引缓冲的
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// 因为索引不会有小数点,所以取用无符号 16 位整型,合理分配内存
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// 最后,将绘制使用的 API 改为使用索引缓冲绘制
// gl.drawArrays(gl.TRIANGLES, 0, 6); 去除该部分内容,改为如下:
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// gl.drawElements(primitiveType, count, indexType, offset);
// 部分参数与 gl.drawArrays 一致。