WebGL 月影带练 | 青训营笔记

84 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第16天,学习的是关于WebGL的内容。

WebGL与GPU

本质上都是运用GPU变形计算的能力

WebGL 是什么?

GPU ≠ WebGL ≠ 3D

WebGL并不简单

现代图形系统

  • 光栅 (Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是指构成图像的像素阵列
  • 像素 (Pixel):一个像素对应图像上的一个点,它通常保存图像上的某个具体位置的颜色等信息。
  • 帧缓存 (Frame Buffer) : 在绘图过程中,像素信息被存放于缓存中,顿缓存是一块内存地址。
  • CPU (Central Processing Unit) : 中央处理单元,负责逻辑计算。
  • GPU (Graphics Processing Unit):图形处理单元,2负责图形计算。

图形系统如何工作

  1. 轮廓提取/meshing
  2. 光栅化(变成点)
  3. (将数据)帧缓存
  4. 渲染

image.png

CPU vs GPU

  • GPU由大量的小运算单元构成
  • 每个运算单元只负责处理很简单的计算
  • 每个运算单元彼此独立
  • 因此所有的计算可以并行处理

WebGL & OpenGL

image.png

WebGL (Web Graphics Library) 和 OpenGL (Open Graphics Library) 是两种不同的图形技术。

WebGL Startup

  1. 创建WebGL上下文
  2. 创建WebGL Program
  3. 将数据存入缓冲区
  4. 将缓冲区数据读取到GPU
  5. GPU执行WebGL程序,输出结果

image.png

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; ++ii) {
    try {
      context = canvas.getContext(names[ii], options);
    } catch (e) {
      // no-empty
    }
    if (context) {
      break;
    }
  }
  return context;
}

The Shaders

1.Vertex Shader

attribute vec2 position;

void main() {
  gl_PointSize = 1.0;
  gl_Position = vec4(position, 1.0, 1.0);
}

2.Fragment Shader

percision mediump float;

void main() {
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

Create Program

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, vertextShader);
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.ARRAT_BUFFER, points, gl.STATIC_DRAW);

Frame Buffer to GPU

const vPosition = gl.getAttribLocation(program, 'position'); //获取顶点着色器中position变量的地址
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0); //给变量设置长度和类型
gl.enableVertexAttribArray(vPosition); //激活这个变量
attribute vec2 position;

void main() {
  gl_PointSize = 1.0;
  gl_Position = vec4(position, 1.0, 1.0);
}

Output

l.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);

image.png

为什么WebGL那么难呢?

用2D编写代码

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

ctx.beginPath();
ctx.moveTo(250, 0);
ctx.lineTo(500, 500);
ctx.lineTo(0, 500);
ctx.fillStyle = 'red';
ctx.fill();

用mesh.js编写代码

import {Renderer, Figure2D, Mesh2D} from '@mesh.js/core';

const canvas = document.querySelector('canvas');
const renderer = new Renderer(canvas);

const figure = new Figure2D();
figure.beginPath();
figure.moveTo(250, 0);
figure.lineTo(500, 500);
figure.lineTo(0, 500);

const mesh = new Mesh2D(figure, canvas);
mesh.setFill({
  color: [1, 0, 0, 1],
});

renderer.drawMeshes([mesh]);

三角剖分可以实现更复杂的图形

  • polygons

image.png

  • triangulations

image.png

使用Earcut进行三角剖分

const vertices = [  [-0.7, 0.5],
  [-0.4, 0.3],
  [-0.25, 0.71],
  [-0.1, 0.56],
  [-0.1, 0.13],
  [0.4, 0.21],
  [0, -0.6],
  [-0.3, -0.3],
  [-0.6, -0.3],
  [-0.45, 0.0],
];

const points = vertices.flat();
const triangles = earcut(points);

image.png

3D Meshing

image.png

Transforms

1.平移

image.png

2.旋转

image.png

3.缩放

image.png

4.旋转+缩放时线性变换

image.png image.png image.png

从线性变换到齐次矩阵

Apply Transforms

attribute vec2 position;
uniform mat3 modelMatrix;
void main() {
  gl_PointSize = 1.0;
  vec3 pos = modelMatrix * vec3(position, 1.0);
  gl_Position = vec4(pos, 1.0);
}
let transform = gl.getUniformLocation(program, 'modelMatrix');
gl.uniformMatrix3fv(transform, false, 
  [0.5, 0, 0, 
   0, 0.5, 0,
   0.1, -0.1, 1]); 

3D Matrix

  • 3D标准模型的四个齐次矩阵(mat4)

    • 投影矩阵Projection Matrix
    • 模型矩阵Model Matrix
    • 视图矩阵View Matrix
    • 法向量矩阵Normal Matrix

Read more