这是我参与「第四届青训营 」笔记创作活动的的第12天,整理一下之前课上关于 WebGL 的知识。
一、本节课重点内容
- 什么是 WebGL
- 如何使用 WebGL
二、详细知识点介绍
1. 什么是 WebGL
WebGL 是在网页上绘制和渲染三维图形的技术,同时可以让用户与其进行交互。WebGL 可以为 HTML Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助 GPU 来在浏览器中更流畅地展示 3D 场景和模型。
2. 现代图形系统中的相关概念
- 光栅(Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是指构成图像的像素阵列
- 像素(Pixel):一个像素对应图像上的一个点,它通常保存图像上某个具体位置的颜色等信息
- 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放在帧缓存中,帧缓存是一块内存地址
- 绘制图形的过程:轮廓提取(meshing)、光栅化、帧缓存、渲染
- GPU(Graphics Processing Unit):图像处理单元,负责图形计算(由于 GPU 由大量的小运算单元构成,每个运算单元只负责处理很简单的计算且彼此独立,因此所有计算可以并行处理,适合对图像中的大量像素点进行处理)
3. 如何使用 WebGL
- 创建 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. 拓展学习
充分理解WebGL - 十年踪迹的专栏 - 掘金 (juejin.cn)
三、课后个人总结
WebGL 是 Web 前端中比较难掌握的一部分内容,一是因为其涉及到很多较为底层的东西,二是因为需要一定的数学知识的储备,但其拥有广泛的应用前景,也是十分值得花时间去学习和掌握的一项技术。之后有时间了要好好学习一下~