WebGL月影带练 | 青训营笔记

69 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天

1. 简介

WebGL代码有两部分:

运行在CPU上的JavaScript

运行在GPU上的GLSL

CPU和GPU:

CPU适合比较复杂的任务,不适合量大但每个单元比较简单的任务 GPU有大量的小运算单元构成,每个运算单元只负责处理简单的计算,每个运算单元彼此独立。所有计算可以并行处理。适合量大但每个单元比较简单的任务。

图像的处理适合交给GPU,因为图像会有很多的像素点需要处理。

图片.png

图片.png

2. 流程

图片.png

1.创建WebGL上下文 图片.png 2.创建WebGL程序,顶点着色器、片元着色器)

顶点着色器(Vertex Shader):

图片.png

片元着色器(Fragment Shader):顶点之间的轮廓中的所有像素都会经过片元着色器处理。(并行处理)

图片.png

图片.png

3.将数据存入缓冲区

图片.png

4.将缓冲区数据读取到GPU

图片.png

5.GPU执行WebGL程序,输出结果

图片.png 完整代码:

// 1. 创建WebGL上下文
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

// 2. 创建WebGL程序

// 2.1 顶点着色器
const vertex = `
  attribute vec2 position;

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

// 2.2 片元着色器
const fragment = `
  precision mediump float;

  void main()
  {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);	// 类似rgba
  }    
`;

// 2.3 加载、编译、使用着色器
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);

const points = new Float32Array([
  -1, -1,
  0, 1,
  1, -1,
]);

// 3. 将数据存入缓存区
const bufferId = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);

// 4. 将缓冲区数据读取到GPU
const vPosition = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(vPosition);

// 5. GPU执行WebGL程序
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);  // points中有六个点,实际上只有三个点,所以需要除以2

图片.png

canvas 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();

3. 多边形

多边形需要进行三角划分

图片.png

4. 变换

  • 平移
  • 旋转
  • 缩放

图片.png