我们已经知道了webgl基本概念,那么WebGL在GPU上究竟做了什么呢?
WebGL在GPU上的工作基本上分为两部分,第一部分是将顶点(或数据流)转换到裁剪空间坐标, 第二部分是基于第一部分的结果绘制像素点。
- 坐标映射:
vertex shader
→gl_Position
- 像素绘制:
fragment shader
→gl_FragColor
比如下述代码:
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 9;
gl.drawArrays(primitiveType, offset, count);
1
2
3
4
2
3
4
这里的9表示“处理9个顶点”,所以将会有9个顶点被转换。
顶点着色器(Vertex Shader)
是你写进GLSL 中的一个方法,每个顶点调用一次,在这个方法中做一些数学运算后设置了一个特殊的gl_Position
变量, 这个变量就是该顶点转换到裁剪空间中的坐标值,GPU接收该值并将其保存起来。
比如绘制三角形:
See the Pen WebGL - Triangle with position for color by Keekuun (@keekuun) on CodePen.
- 定义顶点:
顶点着色器(Vertex Shader)
每完成三次顶点处理,WebGL就会用这三个顶点(gl_Position
)画一个三角形 - 绘制像素:计算出这三个顶点对应的像素后,就会光栅化这个三角形,“
光栅化
”其实就是“用像素画出来” 的花哨叫法。 - 填充颜色:对于每一个像素,它会调用你的
片段着色器
询问你使用什么颜色。 你通过给片段着色器的一个特殊变量gl_FragColor
设置一个颜色值,实现自定义像素颜色。
想要从顶点着色器传值到片段着色器,我们可以定义“可变量(varyings)”。
<canvas id="canvas"></canvas>
<!-- vertex shader -->
<script id="vertex-shader-2d" type="x-shader/x-vertex">
attribute vec2 a_position;
attribute vec4 a_color;
uniform mat3 u_matrix;
varying vec4 v_color; // 定义变量接收
void main() {
// Multiply the position by the matrix.
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
// Copy the color from the attribute to the varying.
v_color = a_color; // 变量赋值
}
</script>
<!-- fragment shader -->
<script id="fragment-shader-2d" type="x-shader/x-fragment">
precision mediump float;
varying vec4 v_color; // 定义同名变量
void main() {
gl_FragColor = v_color; // 变量赋值
}
</script>
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
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
然后:
function main() {
// Get A WebGL context
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("#canvas");
var gl = canvas.getContext("webgl");
if (!gl) {
return;
}
// setup GLSL program
var program = webglUtils.createProgramFromScripts(gl, ["vertex-shader-2d", "fragment-shader-2d"]);
// 询问顶点数据应该放在哪里
// look up where the vertex data needs to go.
var positionLocation = gl.getAttribLocation(program, "a_position");
var colorLocation = gl.getAttribLocation(program, "a_color");
// lookup uniforms
var matrixLocation = gl.getUniformLocation(program, "u_matrix");
// ...
}
main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
关于buffer和attribute的代码是干什么的?
缓冲操作是在GPU上获取顶点和其他顶点数据的一种方式。
gl.createBuffer
创建一个缓冲;gl.bindBuffer
是设置缓冲为当前使用缓冲;gl.bufferData
将数据拷贝到缓冲,这个操作一般在初始化完成。
Demo:
See the Pen WebGL - Fundamentals by Keekuun (@keekuun) on CodePen.