webgl入门指南(一)

一、前言
本文基于MDN技术文档:

https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API

    WebGL 是基于 OpenGL ES 规范的浏览器实现的JavaScript API 。能在任何兼容的Web浏览器中渲染高性能的交互式3D和2D图形。
可以在HTML5 <canvas>元素中使用。
二、基于webgl的开发的库有哪些
    业界有很多基于WebGL开发了一些库,这里广东靓仔列举了一些:

基于webGL开发的库

1、three.js 开源的,功能齐全的3D WebGL库

2、RedGL 是一个开源3D WebGL库 (韩国)

3、vtk.js 是一个JavaScript库,用于在浏览器中进行科学可视

4、babylon.js 基于WebGL的图形引擎

5、Hightopo组件丰富,非开源的付费项目


Three.js的Demo图片预览




















基于Three.js

三、WebGL绘制图形的5个流程
创建 WebGL 上下文

创建 WebGL 程序(WebGLProgram)

将数据存入缓冲区

将缓冲区数据读取到 GPU

GPU 执行 WebGL 程序,输出结果

我们来看看流程图:





    下面我们通过一个Demo来讲解下,这里看不懂的小伙伴不着急,看完Demo回头再看看,会更容易理解。

四、Demo
html
<canvas width="300" height="300"></canvas>
js
html跟Canvas2D一样,我们使用<canvas>元素就可以了

// 调用canvas元素
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
// 俩个着色器
const vertex = `
  // 将缓冲区数据读取到GPU
  attribute vec2 position;  // 声明变量名威position的二维向量
  varying vec3 color;
  void main () {
      gl_PointSize = 1.0;
      color = vec3(0.5 + position * 0.5, 0.0);
      gl_Position = vec4(position * 0.5, 1.0, 1.0);
  }
`
const fragment = `
  precision mediump float;
  varying vec3 color;
  void main () {
      // RGBA 色值表示的四维向量数据
      gl_FragColor = vec4(color, 1.0);
  }
`
// 顶点着色器  片元着色器
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);
 
// 创建program并关联两个shader
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
 
// 启用program
gl.useProgram(program);
 
// 定义三个顶点,类型化数组
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) // 将数据写入缓冲区对象
 
 
// 获取顶点着色器中的position变量的地址
const vPosition = gl.getAttribLocation(program, 'position');
// 给变量设置长度和类型
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
// 激活这个变量
gl.enableVertexAttribArray(vPosition);
 
// 执行着色器完成绘制
gl.clear(gl.COLOR_BUFFER_BIT); // 清空<canvas>
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2); // 绘制三角形
效果如下












demo详解
创建 WebGL直接调用 canvas 元素的 getContext 即可
将参数从2d换成webgl,代码如下:

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl')
从效果图我们可以看到由三个顶点,绘制成一个三角形。
WebGL就是以顶点和图元来绘制几何图形的。
顶点容易理解,图元是 WebGL
可直接处理的图形单元,具体的有7种:

点 gl.POINTS

线段 gl.LINES

线条 gl.LINE_STRIP

回路 gl.LINE_LOOP

三角形 gl.TRIANGLES

三角带 gl.TRIANGLE_STRIP

三角扇 gl.TRIANGLE_FAN

复杂的图形就是由这7个图元拼成的。

效果图里面三角形的颜色就是由顶点着色器、片元着色器处理的。
顶点着色器:它可以改变顶点的信息,从而改变我们绘制出来的图形的形状或者大小等等。
片元着色器:处理光栅化后的像素信息。
光栅化:从顶点着色器和图元提取像素点给片元着色器执行代码的过程。

我们结合代码来理解这概念


顶点着色器和片元着色器代码片段

  // 顶点着色器
  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);


WebGLProgram 对象的创建过程主要是添加 vertexShader 和 fragmentShader,然后将这个 WebGLProgram 对象链接到 WebGL 上下文对象上

// 创建program并关联两个shader
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);


启用这个 WebGLProgram 对象

// 启用program
gl.useProgram(program);


定义好的数据写入 WebGL 的缓冲区

// 定义三个顶点,类型化数组
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) // 将数据写入缓冲区对象
上面代码中,Float32Array,是一个类型化数组。含义即类型化数组对象描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)。


顶点着色器

// 将缓冲区数据读取到GPU
attribute vec2 position;  // 声明变量名position的二维向量
varying vec3 color;
void main () {
    gl_PointSize = 1.0;
    color = vec3(0.5 + position * 0.5, 0.0);
    gl_Position = vec4(position * 0.5, 1.0, 1.0);
}

attribute 表示声明变量,vec2、vec3 是变量的类型,它表示一个二维向量、三维向量,position 是变量名。


把数据绑定给顶点着色器中的 position 变量

// 获取顶点着色器中的position变量的地址
const vPosition = gl.getAttribLocation(program, 'position');
// 给变量设置长度和类型
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
// 激活这个变量
gl.enableVertexAttribArray(vPosition);


执行着色器程序来完成绘制

// 执行着色器完成绘制
gl.clear(gl.COLOR_BUFFER_BIT); // 清空<canvas>
gl.drawArrays(gl.TRIANGLES, 0, points.length / 2); // 绘制三角形
先调用 gl.clear 将当前画布的内容清除,然后调用gl.drawArrays。gl.drawArrays里参数分别表示:
gl.TRIANGLES 表示以三角形为图元绘制、绘制的顶点偏移量、顶点数量

webgl其他知识
1、颜色
2、图案
3、纹理
3、3d(vec3三维)
4、相机
5、光照


五、总结
    在我们阅读完官方文档后,我们要深入学习,可以着重去掌握以下内容:
坐标系转换
参数方程(圆锥曲线、贝塞尔曲线(二、三阶))
向量(叉乘、点乘)
矩阵

作者:广东靓仔


欢迎关注:前端早茶