该文章于一天前宣布在 github,如有题目可提至 github。
在上一篇文章WebGL 初探中,我们熟习了 WebGL 的简朴背景以及怎样绘制一个简朴的点。然则只绘制点我们是没法进入三维天下的,本篇章将解说怎样运用 WebGL 绘制三角形,由于许多 3D 图形都是运用三角形为基础举行衬着的,所以有些对 GPU 性能指标的评价就是衬着三角形的才能。
attribute 变量
前一篇文章中,绘制一个点直接将一个硬编码的矢量赋给了位置属性。然则,明显如许写是不够天真的。所以在这篇文章的前一部分会运用变量重些前一篇文章的例子。我们的目的是将位置自信心从 JavaScript 顺序中通报到极点着色器,而 attribute 变量就传输的是那些和极点相干的数据。下图展现了怎样运用 attribute 变量传输数据:
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
如上所示,前一篇文章中,直接将运用矢量举行赋值 gl_Position = vec4(0.0, 0.0, 0.0, 1.0)
。而这里运用 attribute vec4 a_Position
声明一个 attribute 变量。关键字 attribute 被称为存储限定符,示意声明一个 attribute 变量,而且 attribute 变量必需声明成全局变量,数据将从着色器外传入。gl_Position = a_Position
将 attribute 变量 a_Position 赋值给 gl_Position。
// 取得 attribute 变量 a_Position 的存储位置
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('Failed to get the storage location of a_Position');
return;
}
// 将极点位置通报给 attribute 变量
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
上面,我们运用 vertexAttrib3f(location, v0, v1, v2)
要领将数据 (v0, v1, v2) 通报给 location 参数指向的 attribute 变量。而这里的 location 是要修正的 attribute 变量的存储位置。所以在这之前我们须要猎取 attribute 变量的存储位置。这里,能够经由过程 getAttribLocation(program, name)
猎取 attribute 变量的存储位置。举行完这些变动以后,运转会发明和上一篇文章雷同的结果。
缓冲区对象
到如今,我们一次只能绘制一个点,没法一次性绘制多个点,以至是线和面。想要一次绘制多个点,我们须要借助一个叫做缓冲区对象的东西。缓冲区对象是 WebGL 中的一块存储地区,个中保留了大批的极点数据,能够一次性的向极点着色器传入多个极点到 attribute 变量。下图展现了怎样运用缓冲区对象:
var vertices = new Float32Array([
0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
// 建立缓冲区对象
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer) {
console.log('建立缓冲区对象失利。');
return -1;
}
// 绑定缓冲区对象到目的
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 将数据写入缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0) {
console.log('取得 attriute 变量 a_Position 失利');
return -1;
}
// 将缓冲区对象赋值给 attriute 变量 a_Position
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
// 开启 attribute 变量
gl.enableVertexAttribArray(a_Position);
起首,是经由过程 createBuffer()
要领建立一个缓冲区对象,对应的要领另有 deleteBuffer()
用于删除一个缓冲区对象。接着,运用 bindBuffer(target, buffer)
将缓冲区对象绑定到 WebGL 已存在的目的上,以关照 WebGL 准确的处置惩罚其内容。紧接着,运用 bufferData(target, data, useage)
要领将数据写入缓冲区,这里现实是将数据写入到绑定的目的对象上,所以在第二步中举行了缓冲区对象的绑定。而第二个参数是一个定义好的范例化数组。这里的第三个参数,STATIC_DRAW 代表只会想缓冲区写入一次,绘制屡次,别的用法参数可查相干 API。然后,运用 vertexAttribPointer(location, size, type, normalized, stride, offset)
将缓冲区对象赋值给 attribute 变量。这里的第二个参数制订缓冲区对象的每一个极点的重量(1到4之间),假如 size 比 attribute 变量须要的重量小,则根据肯定划定规矩补全。第三个参数指定了数据格式。第四个参数示意是不是将非浮点型数据归一到 [0, 1] 或[-1,1] 之间。末了两个参数平常默以为0,此处不做详细引见。末了经由过程 enableVertexAttribArray(a_Position)
要领开启缓冲区对象和 attribute 变量的衔接。
绘制三角形
末了,我么可经由过程 drawArrays(gl.TRIANGLES, 0, n)
绘制三角形。然则,前一篇文章中提到 drawArrays 函数功用异常壮大。如今,我们就看一下该函数有哪些壮大的特征。该函数中第一个参数是指定绘制体式格局,第二个参数指定从哪一个极点最先绘制,第三个参数指定绘制须要多少个极点。下表展现了第一个参数对应的绘制体式格局:
参数 | 基础图形 | 显现结果 |
---|---|---|
gl.POINTS | 点 | 一系列的点绘制在v0,v1,v2等处。 |
gl.LINES | 线段 | 一系列零丁线段。 |
gl.LINE_STRIP | 连线 | 一个相连的线段。 |
gl.LINE_LOOP | 回路 | 一个相衔接的回路。 |
gl.TRIANGLES | 三角形 | 一系列零丁的三角形。 |
gl.TRIANGLE_STRIP | 三角带 | 一个相邻三角形构成的图形。 |
下图是 new Float32Array([0, 0.5, -0.5, -0.5, 0.0, 0.0, 0.5, -0.5])
矢量的一个测试:
结语
这篇文章重要讲了怎样应用缓冲区对象在空间中绘制点、线、面。下一篇文章将解说矩阵变更,有了这两个学问的积聚,理论上能够画出我们想要的 3D 图形。WebGL 的 API 看似庞杂,但基础都很相似。当我们对这一套熟习以后,我们会愈发驾轻就熟。