WebGL 与动画实现 | 青训营笔记

113 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第12天,整理一下之前课上关于 WebGL 的知识。

一、本节课重点内容

  1. 什么是 WebGL
  2. 如何使用 WebGL

二、详细知识点介绍

1. 什么是 WebGL

WebGL 是在网页上绘制和渲染三维图形的技术,同时可以让用户与其进行交互。WebGL 可以为 HTML Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助 GPU 来在浏览器中更流畅地展示 3D 场景和模型。

2. 现代图形系统中的相关概念

  • 光栅(Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是指构成图像的像素阵列
  • 像素(Pixel):一个像素对应图像上的一个点,它通常保存图像上某个具体位置的颜色等信息
  • 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放在帧缓存中,帧缓存是一块内存地址
  • 绘制图形的过程:轮廓提取(meshing)、光栅化、帧缓存、渲染
  • GPU(Graphics Processing Unit):图像处理单元,负责图形计算(由于 GPU 由大量的小运算单元构成,每个运算单元只负责处理很简单的计算且彼此独立,因此所有计算可以并行处理,适合对图像中的大量像素点进行处理)

3. 如何使用 WebGL

image.png

  • 创建 WebGL 上下文
const canvas = document.querySelector("canvas")
const gl = canvas.getContext("webgl")

考虑设备兼容性可以进行一层封装

function create3DContext(canvas, options) {
  const names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]
  let context
  for (let name of names) {
    try {
      context = canvas.getContext(name, options)
    } catch (e) {
      console.log(e)
    }
    if (context) {
      break
    }
  }
  return context
}
  • 创建 WebGL Program 顶点着色器(Vertex Shader):用于处理图形轮廓 片元着色器(Fragment Shader):用于处理图形颜色
// 创建顶点着色器
const vertex = ` // 着色器源码
  attribute vec2 position;

  void main() {
    gl_PointSize = 1.0; // 绘制点的大小
    gl_Position = vec4(position, 1.0, 1.0); // 绘制点的坐标
  }
`
const vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertex)
gl.compileShader(vertexShader) // 编译着色器

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

  void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 颜色(RGBA)
  }
`
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)
  • 将数据存入缓存区

WebGL 中的三维坐标系:XY 平面与屏幕平行,X 轴从左向右,Y 轴从下向上,且 (1, 1) 表示屏幕右上角的顶点;Z 轴与屏幕垂直,从外向内

// 三角形三个顶点的坐标
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
const vPosition = gl.getAttribLocation(program, "position") // 获取到边缘着色器源码中 position 这个变量的地址
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0) // 给变量设置长度和类型
gl.enableVertexAttribArray(vPosition) // 激活这个变量
  • GPU 执行 WebGL 程序,输出结果
// 绘制三角形
gl.clear(gl.COLOR_BUFFER_BIT) // 清空颜色缓存区
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2)

绘制多边形的封装库:@mesh.js/core - npm … 三角剖分的开源库:mapbox/earcut: The fastest and smallest JavaScript polygon triangulation library for your WebGL apps (github.com)

4. 图形变换

青训营-WebGL-4 - 码上掘金 (juejin.cn)

5. 拓展学习

image.png

充分理解WebGL - 十年踪迹的专栏 - 掘金 (juejin.cn)

三、课后个人总结

WebGL 是 Web 前端中比较难掌握的一部分内容,一是因为其涉及到很多较为底层的东西,二是因为需要一定的数学知识的储备,但其拥有广泛的应用前景,也是十分值得花时间去学习和掌握的一项技术。之后有时间了要好好学习一下~

四、引用参考