WebGL初体验|青训营笔记

106 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第13天

Modern graphics System--现代图形系统


flowchart LR
	type1[键盘]-->id1[Processor=CPU]
        id1<-->id11[CPU Memory]
	type2[画板]-->id1
	type3[鼠标]-->id1
	id1-->id2[Graphics Processor = GPU]
	id2<-->id22[GPU Memory]
        id2-->id3[Frame Buffer = 帧缓存]
	id3-->id4[渲染在页面上]
  1. 光栅(Raster): 几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是构成图像的像素阵列(点阵)
  2. 像素(Pixel):每一个像素对应图像上的一个点,它通常是保存图像上的某个具体位置的颜色等信息
  3. 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放于帧缓存中,帧缓存是一个内存地址
  4. CPU:中央处理器,负责逻辑运行
  5. GPU:图形处理器,负责图形计算

GPU和CPU干什么

CPU和GPU.jpg

  • 轮廓提取(一般使用三角提取)
  • 光栅化
  • 帧缓存
  • 渲染

我们可以将CPU理解为一个个管道,你有多少核,那么你就有多少个管道(假如你是8核,那么就是八个管道),但是我们的cpu是非常强大的,它可以进行非常复杂的运算,但是如果给的数量太多了,那么效率也不会很高

cpu弊端.png

这时候我们就要借助GPU,它是由大量的小运算单元组成的,他每一个单元只负责简单的计算,每个单元彼此独立,因此计算可以进行并行处理

GPU处理.jpg

WebGL StartUp

  1. 创建WebGL上下文

    const canvas = document,querySelector('canvas');
    const gl = canvas.getContext('webgl')
    
  2. 创建着色器

    • 顶点着色器
    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;
      }    
    `;
    
  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);
    
    
  4. 创建WebGL Program并使用

    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    //使用
    gl.useProgram(program);
    
    
  5. 定义顶点

    const points = new Float32Array([
      -1, -1,
      0, 1,
      1, -1,
    ]);
    
  6. 将数据存在缓存区

    const bufferId = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
    gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
    
  7. 将缓存区数据读取到GPU

    const vPosition = gl.getAttribLocation(program, 'position');
    gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vPosition);
    
  8. GPU执行webGL程序,输出结果

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

webGL可以绘制渐变的,效率会高一点

2D也可以,但是效率不行

阅读资料:

  1. The Book of Shaders
  2. mesh-js/mesh.js: A graphics system born for visualization 😘. (github.com)
  3. SpriteJS ~ Next - 下一代 SpriteJS
  4. Glsl Doodle (webgl.group)
  5. Three.js – JavaScript 3D Library (threejs.org)
  6. Shadertoy BETA