WebGL | 青训营笔记

80 阅读3分钟

这是我参与 [第五届青训营] 伴学笔记创作活动的第15天

WebGL简介

CPU单元运算能力强,适合于复杂的逻辑运算,做精细操作;然而图像处理需要大量运算,但每个单元运算简单——GPU图形处理单元,适合图形计算

WebGL是浏览器的一种运用了GPU能力的渲染方式,WebGL!=3D,WebGL原生上手难度较高

WebGL是利用GPU完成绘制的API,是OpenGL家族成员,可以看作OpenGL的一部分API提供JS接口给浏览器,并在浏览器运行池中实现

WebGL绘制过程:

  1. 通过Canvas对象创建WebGL上下文并获取
  2. 创建WebGL Program(程序),其中在GPU处理图形部分的代码不是JS而是GL/SL,
  3. 将数据存入缓冲区
  4. 将缓冲区数据读取到GPU
  5. GPU执行WebGL程序,输出结果

image-20230214163107527.png

基础使用——绘制三角形

1.获取Canvas

  • 获取canvas对象,并获取canvas的 webgl上下文
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

2.定义着色器(shader)

  • 定义着色器(shaders),在渲染管线上运行在GPU上的图形处理代码(GLSL)
  • 在标准的WebGL管线里有两级着色器:顶点和片源着色器
  • 顶点着色器用来处理图形顶点位置、片段(片源)着色器,处理被顶点和图源定义好的区域内的所有像素点;如三角形包围的区域
  • //在实际绘制中program会拿到position
    //定义4维向量,所以vec4中要加上两个维度
    //片源着色器中设置顶点颜色(1,0,0,1)即红色;由于着色器是并行计算所以只需设置一次
    const vertex = `attribute vec2 position;
    void main() {
      gl_PointSize = 1.0;
      gl_Position = vec4(position, 1.0, 1.0);
    }
    `;
    ​
    const fragment = `precision highp float;
    ​
    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    `
    

3.创建处WebGL程序

  • 通过WebGL上下文创建WebGL程序
  • 通过gl创建shader并编译它
  • 创建好着色器后通过gl创建程序段,把着色器添加到program中
  • 把program链接到gl上,并使用program,最后使用程序让program在上下文生效
  • // 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, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);
    

4.设置坐标点

  • 按照标准右手笛卡尔坐标系定义顶点,接下来将数据传入到缓冲区绘制
  • // set points
    const points = new Float32Array([ //32位浮点数数组
      -1, -1,
      0, 1,
      1, -1,
    ]);
    

5.将点存入缓存

  • 先通过上下文的createBuffer方法创建缓冲区,并将该缓冲区与gl的缓冲区绑定
  • 然后使用bufferData将顶点数据放入到缓冲区中
  • // create & bind Buffer
    const bufferId = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
    gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
    

6.将buffer中的数据映射到WebGL程序中

  • point在缓冲区中要对应上GLSL中的'position'变量
  • 先拿到programposition的指针
  • 通过指针定义好position的类型:float类型的二维向量
  • 把指针激活,这样就可以将buffer-date-point中的数据对应上program-position
  • // FrameBuffer to GPU
    const vPosition = gl.getAttribLocation(program, 'position');
    gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vPosition);
    

7.最后,输出结果

  • 最终输出:
  • 用WebGL上下文清理缓冲区
  • 绘制图形:图源使用三角形,绘制三个点
  • 使用drawArryays后就可以把数据传到shader中
  • // output
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, points.length / 2);
    

绘制效果:

image-20230214214414465.png

总结

WebGL是一种浏览器使用GPU完成绘制的API,其属于OpenGL系列,通过JS接口让浏览器调用并在浏览器运行池中实现。WebGL通过着色器实现图形点以及区域的处理,通过Canvas的WebGL上下文创建WebGL程序,通过缓存与指针向程序输入数据。

WebGL是一门有挑战的技术,使用它可以在浏览器上做出很好的图像,以及3D效果等等