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

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

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;
}
2. 绑定缓冲区对象
gl.bindBuffer()
1
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
3. 将数据写入缓冲区对象
gl.bufferData()
1
gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);
4. 将缓冲区对象分配给一个attribute变量
gl.vertexAttribPointer()
1
2
var a_Position = gl.getAttribLocation(gl.program,'a_Position');
gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);
5. 开启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中的很多操作都要用到类型化数组。

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