WebGL (Web图形库) 是一种JavaScriptAPI,用于在任何兼容的Web浏览器中呈现交互式3D和2D图形,而无需使用插件。WebGL通过引入一个与OpenGL ES 2.0紧密相符合的API,可以在HTML5 canvas 元素中使用。

WebGL完美地解决了现有的Web交互式三维动画的两个问题:第一,它通过HTML脚本本身实现Web交互式三维动画的制作,无需任何浏览器插件支持;第二,它利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的OpenGL接口实现的。

PS:在此之前你需要对3D坐标系,网格、多边形和顶点,材质、纹理和光源,变换和矩阵,相机、透视、视口和投影,着色器等专业术语有一定的了解。

1、怎么在页面上绘制一个webGL图形?

  1. 创建一个画布元素或者容器;
  2. 获取画布的上下文;
  3. 初始化视口;
  4. 创建顶点数组;
  5. 创建矩阵;
  6. 初始化着色器;
  7. 绘制;

2、a sample exampe

(1)创建画布:

1
2
3
4
5
<body>
<canvas id="webgl" width="640" height="480"></canvas>
<script src="../gl-matrix.js"></script>
<script src="./demo2.js"></script>
</body>

(2)获取画布上下文:

1
2
const canvas = document.querySelector('#webgl');
const gl = canvas.getContext('webgl');

(3)初始化着色器:

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
/**
* 缓存器
* @param {any} gl
* @returns
*/
function initBuffers(gl) {

// 创建缓存对象
const positionBuffer = gl.createBuffer();

// 将缓存区对象绑定到目标.
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

// 创建正方形坐标.
const positions = [
1.0, 1.0,
-1.0, 1.0,
1.0, -1.0,
-1.0,-1.0
];

// 将数据拷贝到缓存中
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

return {position: positionBuffer};
}

(4)绘制:

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
62
63
64
65
66
67
68
69
70
/**
* 绘制
* @param {any} gl
* @param {any} programInfo
* @param {any} buffers
*/
function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque
gl.clearDepth(1.0); // Clear everything
gl.enable(gl.DEPTH_TEST); // Enable depth testing
gl.depthFunc(gl.LEQUAL); // Near things obscure far things

// Clear the canvas before we start drawing on it.

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// Create a perspective matrix, a special matrix that is used to simulate the
// distortion of perspective in a camera. Our field of view is 45 degrees, with
// a width/height ratio that matches the display size of the canvas and we only
// want to see objects between 0.1 units and 100 units away from the camera.

const fieldOfView = 45 * Math.PI / 180; // in radians
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const zNear = 0.1;
const zFar = 100.0;
const projectionMatrix = mat4.create();

// note: glmatrix.js always has the first argument as the destination to receive
// the result.
mat4.perspective(projectionMatrix, fieldOfView, aspect, zNear, zFar);

// Set the drawing position to the "identity" point, which is the center of the
// scene.
const modelViewMatrix = mat4.create();

// Now move the drawing position a bit to where we want to start drawing the
// square.

mat4.translate(modelViewMatrix, // destination matrix
modelViewMatrix, // matrix to translate
[-0.0, 0.0, -6.0]); // amount to translate

// Tell WebGL how to pull out the positions from the position buffer into the
// vertexPosition attribute.
{
const numComponents = 2;
const type = gl.FLOAT;
const normalize = false;
const stride = 0;
const offset = 0;
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
// WebGL 会从缓存中获取数据,这个缓存会与 gl.bindBuffer 绑定
gl.vertexAttribPointer(programInfo.attribLocations.vertexPosition, numComponents, type, normalize, stride, offset);
// 将缓存中的数据复制给变量
gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
}

// Tell WebGL to use our program when drawing
gl.useProgram(programInfo.program);

// Set the shader uniforms
gl.uniformMatrix4fv(programInfo.uniformLocations.projectionMatrix, false, projectionMatrix);
gl.uniformMatrix4fv(programInfo.uniformLocations.modelViewMatrix, false, modelViewMatrix);

{
const offset = 0;
const vertexCount = 4;
gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount);
}
}

3、学习资料