更新于 

绘制多个点

三维模型的基本单位是什么?

答: 三角形 △
不管三维模型的形状多么复杂,基本组成单位都是三角形。
只不过复杂的模型由更多的三角形构成而已。

MultiPoint

缓冲区对象(buffer object)

如果你要绘制一个图形,你需要一次性的将图形的顶点全部传入Vertex_Shader
缓冲区对象 支持一次性地向shader传入多个顶点的数据。
它是WebGL系统中的一块内存区域

MultiPoints Code
MultiPoints绘制效果
MultiPoints绘制效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../examples/lib/cuon-utils.js"></script>
<script src="../examples/lib/webgl-debug.js"></script>
<script src="../examples/lib/webgl-utils.js"></script>
<script src="./MultiPoints.js"></script>
</head>
<body onload="main()">
<canvas id="webgl" width="500" height="300"></canvas>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 顶点着色器
var VSHADER_SOURCE =
`
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
gl_PointSize = 10.0;
}
`;
// 片元着色器
var FSHADER_SOURCE =
`
void main(){
gl_FragColor = vec4(0.0,1.0,0.0,1.0);
}
`
function main() {
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE);

// 设置顶点位置
var n = initVertexBuffers(gl);
if (n < 0) {
console.log('设置顶点位置失败');
return;
}

gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, n);
}

function initVertexBuffers(gl) {
var vertices = new Float32Array([
0.0, 0.5, -0.5, -0.5, 0.5, -0.5
]);
var n = 3; //点数

// 创建缓冲区对象
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');

// 将缓冲区对象分配给a_Position变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

// 连接a_Position变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
return n;
}
使用缓冲区对象流程

缓冲区对象是WebGL系统中的一块存储区。

  1. 创建缓冲区对象
gl.createBuffer()
1
2
3
4
5
var vertexBuffer = gl.createBuffer();
if(!vertexBuffer){
console.log('Failed to create the buffer object');
return -1;
}
  1. 绑定缓冲区对象
gl.bindBuffer()
1
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  1. 将数据写入缓冲区对象
gl.bufferData()
1
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
  1. 将缓冲区对象分配给一个attribute变量
gl.vertexAttribPointer()
1
2
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
  1. 开启attribute变量
gl.enableVertexAttribArray()
1
gl.enableVertexAttribArray(a_Position);
步骤分解
1. 创建缓冲区对象
gl.createBuffer()
缓冲区对象可以被

创建删除

createBuffer
createBuffer
deleteBuffer
deleteBuffer
2. 绑定缓冲区对象
gl.bindBuffer()

缓冲区对象 绑定到WebGL系统中已经存在的 target 上,
这个 target 表示 缓冲区对象的用途

bindBuffer
bindBuffer
3. 写入缓冲区对象
gl.bufferData()

不能直接向缓冲区写入数据,只能向与缓冲区绑定的目标写入数据。

bufferData
bufferData
4. 分配attribute变量给缓冲区对象
gl.vertexAttribPointer()

vertexAttribPointer可以将整个缓冲区对象的引用分配给attribute变量

vertexAttribPointer
vertexAttribPointer
5. 开启attribute对象
gl.enableVertexAttribArray()

通过enableVertexAttribArray,
缓冲区对象和attribute变量之间的连接就真正建立起来了。

enableVertexAttribArray函数名会让很多人误解它是用于处理顶点的,这是由于继承自OpenGL

缓冲区对象与attribute变量之间的连接可以通过 enableVertexAttribArray 建立,
同时也可以通过 disableVertexAttribArray 关闭。

enableVertexArray
enableVertexArray
disableVertexArray
disableVertexArray
6. 开始绘制
gl.drawArrays()

shader的执行次数与drawArrays的count参数相一致。

因此在MultiPoints中,Shader实际上被执行了3次。
顶点着色器执行过程中缓冲区数据的传输过程
顶点着色器执行过程中缓冲区数据的传输过程

下面是2个对于gl.drawArrays函数的小实验:

drawArrays(gl.POINTS,0,1)
drawArrays(gl.POINTS,1,2)

类型化数组

WebGL中的很多操作都要用到类型化数组。

提示:
  • 类型化数组不支持 pushpop
  • 创建类型化数组的唯一方法就是使用 new运算符
WebGL使用的各种类型化数组
WebGL使用的各种类型化数组
类型化数组的方法、属性和常量
类型化数组的方法、属性和常量