这是我参与「第五届青训营」笔记创作活动的第15天。
Why WebGL / Why GPU
-
WebGL是什么?
- GPU ≠ WebGL ≠ 3D
-
WebGL为什么不像其他前端技术那么简单?
Modern Graphics System
- 光栅(Raster):几乎所有的现代图形系统都是基于光栅绘制图形的,光栅就是构成图像的像素阵列
- 像素(Pixel):一个像素对应图像上的一个点,它通常保存图像上的某个具体位置的颜色等信息
- 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放于帧缓存中,帧缓存是一块内存地址
- CPU(Central Processing Unit):中央处理单元,负责逻辑计算
- GPU(Graphics Processing Unit):图形处理单元,负责图形计算
- 轮廓提取(CPU)
- 光栅化(GPU)
- 帧缓存
- 渲染
The Pipeline
管线:数据——>处理——>帧缓存——>渲染像素
GPU
GPU由大量小运算单元构成,每个运算单元独立的负责处理简单的运算,因此所有计算可以并行处理
WebGL Startup
-
创建WebGL上下文
// Create WebGL Context const canvas = document.querySelector('canvas') const gl = canvas.getContext('webgl') function create3DContext(canvas, options) { const names = ['webgl', 'experimental-webgl', 'webkit-3d', 'moz-webgl'] if (options.webgl2) names.unshift('webgl2') let context = null for (let ii = 0; ii < names.length; ++i) { try { context = canvas.getContext(names[ii], options) } catch (e) { // no-empty } if (context) { break; } } return context } -
创建WebGL Program
const vertex = ` attribute vec2 position; varying vec4 color; void main() { gl_PointSize = 1.0; gl_Position = vec4(position, 1.0, 1.0); color = vec4(0.5 * (vec2(1.0) + position), 0.0, 1.0); } ` const fragment = ` precision mediump float; varying vec4 color; void main() { // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); gl_FragColor = color; } ` const vertexShader = gl.createShader(gl.VERTEX_SHADER) gl.shaderSource(vertexShader, vertex) gl.compileShader(vertexShader) const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER) gl.shaderSource(fragmentShader, fragment) gl.compileShader(fragmentShader); const program = gl.createProgram() gl.attachShader(program, vertexShader) gl.attachShader(program, fragmentShader) gl.linkProgram(program) gl.useProgram(program) -
将数据存入缓存区
// Data to Frame Buffer const points = new Float32Array([-1, -1, 0, 1, 1, -1]) const bufferId = gl.createBuffer() gl.bindBuffer(gl.ARRAY_BUFFER, bufferId) gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW) -
读取缓冲区数据到GPU
// Frame Buffer to GPU const vPosition = gl.getAttribLocation(program, 'position') gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0) gl.enableVertexAttribArray(vPosition) -
GPU执行WebGL程序,输出结果
// Output gl.clear(gl.COLOR_BUFFER_BIT) gl.drawArrays(gl.TRIANGLES, 0, points.length / 2)
为什么WebGL那么难 ?
-
2D
const canvas = document.querySelector('canvas') const ctx = canvas.getContext('2d') ctx.beginPath() ctx.moveTo(200, 0) ctx.lineTo(400, 400) ctx.lineTo(0, 400) ctx.fillStyle = 'red' ctx.fill() -
Mesh.js
const canvas = document.querySelector('canvas') const renderer = new Renderer(canvas) const figure = new Figure2D() figure.beginPath() figure.moveTo(200, 0) figure.lineTo(400, 400) figure.lineTo(0, 400) const mesh = new Mesh2D(fugure, canvas) mesh.setFill({ color: [1, 0, 0, 1] }) renderer.drawMeshes([mesh])
3D Matrix
3D标准模型有四个齐次矩阵(mat4)
- 投影矩阵 Projection Matrix
- 模型矩阵 Model Matrix
- 视图矩阵 View Matrix
- 法向量矩阵 Normal Matrix