这是我参与「第四届青训营」笔记创作活动的第13天
Why WebGL?
- 现代图形系统
- 概念
- 光栅 Raster
- 构成图像的像素阵列
- 像素 Pixel
- 帧缓存 Frame Buffer
- 存放像素信息的一块内存地址
- CPU
- GPU
- 光栅 Raster
- 绘制过程
- 轮廓提取 / meshing
- 对轮廓网格化,平面和3D面通常用三角网格
- 光栅化
- 帧缓存
- 渲染
- 轮廓提取 / meshing
- 渲染管线 Pipeline
- Data ->
Processor -> Frame Buffer-> Pixels
- Data ->
- 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
- 光栅化后处理颜色
- 顶点着色器 Vertex 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]
- HTML坐标系
- 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物体表面的法线信息
- 与光线射到物体表面的反射有关,计算法线夹角
- 投影矩阵
- 3D标准模型的四个齐次矩阵(mat4)
- 类型