初识WebGL(1) | 青训营笔记

68 阅读3分钟

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

Why WebGL?

  • 现代图形系统
    • 概念
      • 光栅 Raster
        • 构成图像的像素阵列
      • 像素 Pixel
      • 帧缓存 Frame Buffer
        • 存放像素信息的一块内存地址
      • CPU
      • GPU
    • 绘制过程
      • 轮廓提取 / meshing
        • 对轮廓网格化,平面和3D面通常用三角网格
      • 光栅化
      • 帧缓存
      • 渲染
    • 渲染管线 Pipeline
      • Data -> Processor -> Frame Buffer -> Pixels
    • CPU vs GPU
      • 沙子过一两个大管道 VS 沙子过大量小管道
      • CPU批量处理像素效率相对较低
      • GPU由大量的小运算单元构成,计算可以并行处理
        • 每个运算单元只负责处理很简单的计算
        • 每个运算单元彼此独立
    • WebGL & OpenGL
      • OpenGL -> OpenGL ES(对应嵌入式设备) -> WebGL(对应Web版本)
      • 参考资料

WebGL Usage

  • WebGL Startup
    • 创建WebGL上下文
    • 创建WebGL Program
    • 将数据存入缓冲区
    • 将缓冲区数据读取到GPU
    • GPU执行WebGL程序,输出结果
  • 创建WebGL上下文
// 创建WebGL上下文(不考虑兼容性)
const canvas = document.querySelector('canvas')
const gl = canvas.getContext('webgl')
  • 写着色器 Shaders
    • 顶点着色器 Vertex Shader
      • 处理图形轮廓
    • 片源着色器 Fragment Shader
      • 光栅化后处理颜色
  • 创建WebGL Program
// 创建WebGL 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)
  • 将数据存入缓冲区
    • 浏览器中的坐标系
      • HTML坐标系
        • 以左上角为原点
        • X轴向右,Y轴向下
      • WebGL坐标系
        • 以canvas的中心点为原点
        • X轴向右,Y轴向上,Z轴向外
        • 坐标归一化,默认X轴和Y轴的坐标在[-1.0,1.0]
    • WebGL渲染的类型区别
      • 区分整数、浮点数等
      • 通过Typed Array记录类型信息
// 将数据存入缓冲区  
// 例: 创建一个三角形  
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
    • 通过着色器执行WebGL的Program
    • 在这个过程传入一些attribute数据,比如顶点数据
    • 传入六个值,一个顶点着色器处理两个,三个顶点着色器并行计算
    • WebGL中的rgba的四个参数是浮点数,取值[0.0, 1.0]
// 将缓冲区数据读取到GPU  
const vPosition = gl.getAttribLocation(program, 'position') // 获取顶点着色器中position变量的地址  
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0) // 给变量设置长度和类型  
gl.enableVertexAttribArray(vPosition) // 激活这个变量
  • GPU执行WebGL程序,输出结果
    • 示例中FragmentShader可以读取到VertexShader里的color
// GPU执行WebGL程序,输出结果  
gl.clear(gl.COLOR_BUFFER_BIT) // 初始化颜色缓冲区  
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2)
  • WebGL vs 2d
    • 2d里用path绘制轮廓
    • WebGL处理渐变颜色的情况有优势
    • WebGL处理大量图形有性能优势
  • 绘制多边形
    • 开源库Mesh.js对多边形进行了一些封装
    • 在WebGL一般用三角剖分(Triangulations)的方式绘制
    • 简单多边形可以用Earcut进行三角剖分
    • 3D meshing
      • 在设计工具里实时绘制时进行三角剖分
      • 示例
  • Transforms
    • 类型
      • 平移
      • 旋转
      • 缩放
    • 用一个齐次矩阵将三个操作归为一个线性变换,如CSS里的transfrom-2d属性
    • uniform类型的变量值不变
    • attribute类型的变量值可变
    • 3D Matrix
      • 3D标准模型的四个齐次矩阵(mat4)
        • 投影矩阵 Projection Matrix
          • 用来处理坐标系
        • 模型矩阵 Model Matrix
          • 对模型做线性变换
        • 视图矩阵 View Matrix
          • 根据3D视图的视角即“摄像机”改变
        • 法向量矩阵 Normal Matrix
          • 3d物体表面的法线信息
          • 与光线射到物体表面的反射有关,计算法线夹角