WebGL

1、WebGL上下文

  • 在完全支持的浏览器中:
    • **WebGL 2.0上下文的名字叫” webgl2”**;
    • **WebGL 1.0上下文的名字叫” webgl1”**。
  • 检测浏览器是否支持WebGL:
1
2
3
4
5
6
7
8
let drawing = document.getElementById("drawing"); 
// 确保浏览器支持<canvas>
if (drawing.getContext) {
let gl = drawing.getContext("webgl");
if (gl){
// 使用 WebGL
}
}

2、WebGL基础

  • 可以在调用getContext ()取得WebGL上下文时指定一些选项。这些选项通过一个参数对象传入,选项就是参数对象的一个或多个属性。
1
2
3
4
5
6
7
8
let drawing = document.getElementById("drawing"); 
// 确保浏览器支持<canvas>
if (drawing.getContext) {
let gl = drawing.getContext("webgl", { alpha: false });
if (gl) {
// 使用 WebGL
}
}

1)常量

  • 常量在OpenGL中的名字以GL_开头。在WebGL 中,context对象上的常量则不包含GL_前缀。

2)方法命名

  • 接收不同类型和不同数量参数的方法,会通过方法名的后缀体现这些信息。
  • 表示参数数量的数字(1~4)在先,表示数据类型的字符串(“f”表示浮点数,”i”表示整数)在后,还有很多方法接收数组,这类方法用字母“v”(vector )来表示。
  • 比如,gl.uniform4f()的意思是需要4个浮点数值参数,gl.uniform3iv()就是要接收一个包含3个值的数组参数。

3)准备绘图

  • 准备使用WebGL上下文之前,通常需要先指定一种实心颜色清除<canvas>。为此,要调用clearcolor()方法并传入4个参数,分别表示红、绿、蓝和透明度值。每个参数必须是0~1范围内的值,表示各个组件在最终颜色的强度。
1
2
gl.clearColor(0, 0, 0, 1); // 黑色
gl.clear(gl.COLOR_BUFFER_BIT);

4)视口与坐标

  • 绘图前还要定义WebGL 视口。默认情况下,视口使用整个<canvas>区域。
  • 要改变视口,可以调用viewport()方法并传入视口相对于<canvas>元素的x、y坐标及宽度和高度。
1
gl.viewport(0, 0, drawing.width,drawing.height);
  • 这个视口的坐标系统与网页中通常的坐标系统不一样。视口的x和y坐标起点(0,0)表示<canvas>元素的左下角,向上、向右增长可以用点(width-1, height-1)定义。
1
2
3
4
5
6
// 视口是<canvas> 左下角四分之一区域
gl.viewport(0, 0, drawing.width/2, drawing.height/2);
// 视口是<canvas> 左上角四分之一区域
gl.viewport(0, drawing.height/2, drawing.width/2, drawing.height/2);
// 视口是<canvas> 右下角四分之一区域
gl.viewport(drawing.width/2, 0, drawing.width/2, d

5)缓冲区

  • gl.createBuffer()方法用于创建缓冲区。
  • gl.bindBuffer()方法用于将缓冲区绑定到WebGL上下文。绑定后就可以用数据填充缓冲区了。
1
2
3
4
let buffer = gl.createBuffer(); 
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
//初始化buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, 1]), gl.STATIC_DRAW);
  • drawElements()方法同时传入gl.ELEMENT_ARRAY_BUFFER可用于输出缓冲区内容。
  • gl.bufferData()方法的最后一个参数表示如何使用缓冲区。这个参数可以是以下常量值。

6)错误

  • gl.getError()方法
    • 方法返回一个常量,表示发生的错误类型,下面列出了这些常量:
  • 每次调用gl.getError()方法会返回一个错误值。第一次调用之后,再调用gl.getError ()可能会返回另一个错误值。如果有多个错误,则可以重复这个过程,直到 gl.getError ()返回gl.NO_ERROR。

7)着色器

  • WebGL 中有两种着色器:顶点着色器片段(或像素)着色器
    • 顶点着色器用于把3D顶点转换为可以渲染的2D点。
    • 片段着色器用于计算绘制一个像素的正确颜色。
  • WebGL着色器的独特之处在于,它们不是JavaScript实现的,而是使用一种与C或JavaScript完全不同的语言GLSL ( OpenGL Shading Language)写的。

8)绘图

  • WebGL只能绘制三种形状:点、线和三角形
  • drawArrays()方法:使用数组缓冲区
    • 接收三个参数:常量、数组缓冲区起点索引、数组缓冲区包含的顶点集合的数量。
  • drawElements()操作元素数组缓冲区。

9)纹理

  • gl.createTexture()方法创建新的纹理,然后将图片绑定到这个纹理。
  • 如果图片还没有加载,则可以创建一个 Image对象来动态加载。图片加载完成后才能初始化纹理,因此在图片的load事件之后才能使用纹理。
1
2
3
4
5
6
7
8
9
10
11
12
13
let image = new Image(), 
texture;
image.src = "smile.gif";
image.onload = function() {
texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
// 除当前纹理
gl.bindTexture(gl.TEXTURE_2D, null);
}

10)读取像素

  • readPixels()方法。
    • 参数包括:x、y坐标、宽度、高度、图像格式、类型和定型数组。
1
2
let pixels = new Uint8Array(25*25); 
gl.readPixels(0, 0, 25, 25, gl.RGBA, gl.UNSIGNED_BYTE, pixels);