缓冲区
缓冲区对象是 webgl 系统中提供的一块存储区,可以在其中保存想要绘制的所有顶点的数据,然后一次性向顶点着色器中传入数据。

使用缓冲区对象向顶点着色器传入数据的步骤为:
- 创建缓冲区对象(
gl.createBuffer) - 绑定缓冲区对象(
gl.bindBuffer) - 将数据写入缓冲区对象(
gl.bufferData) - 将缓冲区对象分配给一个 attribute 变量(
gl.vertexAttribPointer) - 开启 attribute 变量(
gl.enableVertexAttribArray)
使用webgl缓冲区绘制点的代码示例:
const canvas = document.getElementById('canvas')
const gl = canvas.getContext('webgl')
// 顶点着色器
const VSHADER_SOURCE = [
'attribute vec4 a_Position;',
'void main() {',
' gl_Position = a_Position;', // 定义点的位置
' gl_PointSize = 10.0;', // 定义点的大小
'}',
].join('\n')
// 片原着色器
const FSHADER_SOURCE = [
'void main() {',
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);',
'}',
].join('\n')
// initShader 定义在 utils/index.js 中,用于创建 program 并绑定着色器
if (gl && GlHelper.initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
gl.clearColor(0.0, 0.0, 0.0, 1.0)
gl.clear(gl.COLOR_BUFFER_BIT)
const a_Position = gl.getAttribLocation(gl.program, 'a_Position')
const vertices = new Float32Array([
0, 0, 0.5, 0.5, -0.5, -0.5
])
// 创建缓冲区
const vertexBuffer = gl.createBuffer()
if (!vertexBuffer) {
console.error('创建Buffer失败!')
} else {
// 绑定缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
// 将数据写入缓冲区
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
// 指定变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
// 开启变量
gl.enableVertexAttribArray(a_Position)
// 绘制缓冲区内的数据
gl.drawArrays(gl.POINTS, 0, 3)
}
}
drawArrays
gl.drawArrays(mode, start, end)提供了绘制点、线、回路等绘制模式,通过第一个参数指定不同的值,就能以 7 种不同的方式来绘制图形。
| 基本图形 | 参数 mode | 描述 |
|---|---|---|
| 点 | gl.POINTS | 绘制 v0,...,vn 的点 |
| 三角形 | gl.LINES | 按照 (v0, v1),(v2,v3),... 规则绘制线,点数不足将忽略 |
| 线条 | gl.LINE_STRIP | 按照 (vs, vs+1),(vs+1,vs+2),... 规则绘制线 |
| 回路 | gl.LINE_LOOP | 按照 (vs, vs+1),(vs+1,vs+2),... 规则绘制线 |
| 三角形 | gl.TRIANGLES | 按照(v0, v1, v2),(v3, v4, v5),... 的规则绘制三角形,点数不足将忽略 |
| 三角带 | gl.TRIANGLE_STRIP | 按照(v0, v1, v2),(v1, v2, v3),... 的规则绘制三角形 |
| 三角扇 | gl.TRIANGLE_FAN | 按照(v0, v1, v2),(v0, v2, v3),... 的规则绘制三角形 |
下面我们用 Demo 来看下各种图形是怎么样的: 使用 drawArrays 绘制更多图形
Demo 中我们采用不同的方式绘制了同样的缓冲区数据,得到了7中不同结果,可以结合 Demo 去理解每种类型分别的绘制规则。
// Demo中绘制的缓冲区数据
const vertices = new Float32Array([
0, -0.5, 0.5, 0, 0, 0.5, -0.5, 0
])
变换
如果用 JS 写过动画的同学应该知道,可以通过相隔指定时间修改元素的宽、高等属性,来实现元素的动画,同样的方法我们可以通过修改指定图形的坐标来调整绘制图形的位置,进而实现动画。
由于 webgl 是建立在三维坐标系上的,对三维坐标的变换就不得不提到矩阵,这里不做详细介绍,只提供平移、旋转、缩放的简单公式,仅供参考。
平移
x' = x + Tx
y' = y + Ty
z' = z + Tz
平移就是图形上的点全部加上相同的距离,可以通过调整 Tx、Ty、Tz 的值来实现曲线的平移效果。
旋转
x' = x * cosα - y * sinα
y' = x * sinα + y * cosα
z' = z
上述公式表明了,将图形以 z 轴旋转 α 角度时,x、y 的坐标变换公式。
缩放
x' = S * x
y' = S * y
z' = S * z
啊,这个很好理解,乘以缩放系数就对了。