webgl使用
https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext

  1. var canvas = document.getElementById('myCanvas');
  2. // 返回WebGLRenderingContent对象
  3. var gl = canvas.getContext('webgl');

webgl-utils.js,webgl-debug.js,cuon-utils.js 到下面的地址去下载
https://github.com/GrayMind/WebGL-Programming-Guide

1、清空绘图区

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>Clear canvas</title>
  6. </head>
  7. <body>
  8. <canvas id="webgl" width="400" height="400">
  9. Please use the browser supporting "canvas"
  10. </canvas>
  11. <script src="./lib/webgl-utils.js"></script>
  12. <script src="./lib/webgl-debug.js"></script>
  13. <script src="./lib/cuon-utils.js"></script>
  14. <script>
  15. function main() {
  16. // 获取 <canvas> 元素
  17. var canvas = document.getElementById('webgl');
  18. // 获取 WebGL 绘图上下文
  19. var gl = getWebGLContext(canvas);
  20. if (!gl) {
  21. console.log('Failed to get the rendering context for WebGL');
  22. return;
  23. }
  24. // 设置背景颜色
  25. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  26. // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
  27. // gl.COLOR_BUFFER_BIT 颜色缓冲区
  28. // 清空颜色缓冲区
  29. gl.clear(gl.COLOR_BUFFER_BIT);
  30. }
  31. debugger
  32. main()
  33. </script>
  34. </body>
  35. </html>

image.png

2、绘制一个点

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="./lib/webgl-utils.js"></script>
  <script src="./lib/webgl-debug.js"></script>
  <script src="./lib/cuon-utils.js"></script>
  <script>
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = 
        'void main() {\n' +
        // vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴
        // w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
        '  gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n' + // 设置点的位置
        '  gl_PointSize = 10.0;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色气
      var FSHADER_SOURCE =
        'void main() {\n' +
        '  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      setShaders(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.drawArrays(gl.POINTS, 0, 1);
    }

    main()

  </script>
</body>

</html>

2.1、绘制一个点(版本2),使用attribute变量,使用uniform变量

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'void main() {\n' +
        // vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
        // w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
        '  gl_Position = a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色气
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_Position < 0 || a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      setShaders(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);

      gl.drawArrays(gl.POINTS, 0, 1);
    }

    main()

  </script>
</body>

</html>

3、使用缓冲区绘制多个点

1、创建缓冲区对象
const buffer = gl.createBuffer()
2、将缓冲区对象绑定到target对象上
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
3、将顶点坐标数据写入缓冲区对象
gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW)
4、将顶点坐标数据分配给对应的attribute变量
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
5、开启attribute变量
gl.enableVertexAttribArray(a_Position)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'void main() {\n' +
        // vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
        // w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
        '  gl_Position = a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色气
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      var initVertexBuffers = function () {
        // 1.创建缓冲区对象
        // gl.dleteBuffer(buffer); 删除缓冲区对象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          throw new TypeError("创建缓冲区失败");
        }

        var vertices = new Float32Array([
          0.0, 0.5,
          -0.5, -0.5,
          0.5, -0.5
        ])

        // 2.绑定缓冲区对象到目标
        // gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT|ARRAY_BUFFER|buffer, buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 3.向缓冲区写入数据
        // gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER, data, usage);
        // usage gl.STATIC_DRAW | gl.STREAM_DRAW | gl.DYNAMIC_DRAW
        // gl.STATIC_DRAW: 只会想缓冲区对象写入一次数据,但需要绘制很多次
        // gl.STREAM_DRAW: 只会想缓冲区对象写入一次数据,然后绘制若干次
        // gl.DYNAMIC_DRAW: 会向缓冲区对象中多次写入数据,并绘制很多次
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        // 4.将缓冲区对象分配给变量
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          throw new TypeError("无法获取变量的存储位置")
        }
        // gl.vertexAttribPointer(location, size, type, normalize, stride, offset);
        // location 就是变量
        // size 可选值是 1-4,和vec4的赋值一样
        // type 表示类型,gl.FLOAT 浮点型,gl.INT(int32Array) 整形,...
        // normalize 传入true或false,表明是否将非浮点型的数据归一化到[1,0]或[-1,1]区间
        // stride 指定相邻两个顶点间的字节数,默认为0
        // offset 指定缓冲区对象中的偏移量(以字节为单位)即attribute变量从缓冲区中何处开始存储。如果从起始位置开始,offset设置为0
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        // 5.连接a_Poistion变量于分配给它缓冲区对象
        // 开启变量 gl.enableVertexAttribArray(location);
        gl.enableVertexAttribArray(a_Position);

        return 3;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);
      // gl.drawArrays(mode, first, count);
      // mode 表示绘制的方式
      // first 从那个顶点开始绘制
      // count 绘制几个顶点
      gl.drawArrays(gl.POINTS, 0, n);
    }

    main()

  </script>
</body>

</html>

3.1绘制正方形

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'void main() {\n' +
        // vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
        // w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
        '  gl_Position = a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色气
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      var initVertexBuffers = function () {
        // 1.创建缓冲区对象
        // gl.dleteBuffer(buffer); 删除缓冲区对象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          throw new TypeError("创建缓冲区失败");
        }

        // 三角形
        var TRIANGLE = [
          0.0, 0.5,
          -0.5, -0.5,
          0.5, -0.5
        ]

        // 正方形
        var square = [
          -0.5, 0.5, // v0
          -0.5, -0.5, // v1
          0.5, 0.5, // v2
          0.5, -0.5 // v3
        ]

        var vertices = new Float32Array(square);

        // 2.绑定缓冲区对象到目标
        // gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT|ARRAY_BUFFER|buffer, buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 3.向缓冲区写入数据
        // gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER, data, usage);
        // usage gl.STATIC_DRAW | gl.STREAM_DRAW | gl.DYNAMIC_DRAW
        // gl.STATIC_DRAW: 只会想缓冲区对象写入一次数据,但需要绘制很多次
        // gl.STREAM_DRAW: 只会想缓冲区对象写入一次数据,然后绘制若干次
        // gl.DYNAMIC_DRAW: 会向缓冲区对象中多次写入数据,并绘制很多次
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        // 4.将缓冲区对象分配给变量
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          throw new TypeError("无法获取变量的存储位置")
        }
        // gl.vertexAttribPointer(location, size, type, normalize, stride, offset);
        // location 就是变量
        // size 可选值是 1-4,和vec4的赋值一样
        // type 表示类型,gl.FLOAT 浮点型,gl.INT(int32Array) 整形,...
        // normalize 传入true或false,表明是否将非浮点型的数据归一化到[1,0]或[-1,1]区间
        // stride 指定相邻两个顶点间的字节数,默认为0
        // offset 指定缓冲区对象中的偏移量(以字节为单位)即attribute变量从缓冲区中何处开始存储。如果从起始位置开始,offset设置为0
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        // 5.连接a_Poistion变量于分配给它缓冲区对象
        // 开启变量 gl.enableVertexAttribArray(location);
        gl.enableVertexAttribArray(a_Position);

        return 4;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);


      // gl.POINTS 点
      // gl.LINES 线段,此时只画出一条线段(一次画一条)
      // gl.LINE_STRIP 线条,此时画出两条线,但是没有闭合线段
      // gl.LINE_LOOP 回路,一个三角形被画出来,但是都是线段的,没有填充
      // gl.TRIANGLES 三角形,一个三角形被画出来,填充了颜色
      // gl.TRIANGLES_STRIP 三角带
      // g.TRIANGLE_FAN 三角扇
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    }

    main()

  </script>
</body>

</html>

3.2 位移

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色器
      var VSHADER_SOURCE = 
        'uniform vec4 u_Translation;\n'+ // 设置偏移位置
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'void main() {\n' +
        // a_Position     v1 v2 v3 v4
        // 加              +  +  +  +
        // u_Translation  v1 v2 v3 v4
        '  gl_Position = a_Position + u_Translation;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色器
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      var initVertexBuffers = function () {
        // 1.创建缓冲区对象
        // gl.dleteBuffer(buffer); 删除缓冲区对象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          throw new TypeError("创建缓冲区失败");
        }

        // 三角形
        var TRIANGLE = [
          0.0, 0.5,
          -0.5, -0.5,
          0.5, -0.5
        ]

        // 正方形
        var square = [
          -0.5, 0.5, // v0
          -0.5, -0.5, // v1
          0.5, 0.5, // v2
          0.5, -0.5 // v3
        ]

        var vertices = new Float32Array(square);

        // 2.绑定缓冲区对象到目标
        // gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT|ARRAY_BUFFER|buffer, buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 3.向缓冲区写入数据
        // gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER, data, usage);
        // usage gl.STATIC_DRAW | gl.STREAM_DRAW | gl.DYNAMIC_DRAW
        // gl.STATIC_DRAW: 只会想缓冲区对象写入一次数据,但需要绘制很多次
        // gl.STREAM_DRAW: 只会想缓冲区对象写入一次数据,然后绘制若干次
        // gl.DYNAMIC_DRAW: 会向缓冲区对象中多次写入数据,并绘制很多次
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        // 4.将缓冲区对象分配给变量
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          throw new TypeError("无法获取变量的存储位置")
        }

        var u_Translation = gl.getUniformLocation(gl.program, "u_Translation");
        gl.uniform4f(u_Translation, 0.5, 0.5, 0.5, 0.0); 

        // gl.vertexAttribPointer(location, size, type, normalize, stride, offset);
        // location 就是变量
        // size 可选值是 1-4,和vec4的赋值一样
        // type 表示类型,gl.FLOAT 浮点型,gl.INT(int32Array) 整形,...
        // normalize 传入true或false,表明是否将非浮点型的数据归一化到[1,0]或[-1,1]区间
        // stride 指定相邻两个顶点间的字节数,默认为0
        // offset 指定缓冲区对象中的偏移量(以字节为单位)即attribute变量从缓冲区中何处开始存储。如果从起始位置开始,offset设置为0
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        // 5.连接a_Poistion变量于分配给它缓冲区对象
        // 开启变量 gl.enableVertexAttribArray(location);
        gl.enableVertexAttribArray(a_Position);

        return 4;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);


      // gl.POINTS 点
      // gl.LINES 线段,此时只画出一条线段(一次画一条)
      // gl.LINE_STRIP 线条,此时画出两条线,但是没有闭合线段
      // gl.LINE_LOOP 回路,一个三角形被画出来,但是都是线段的,没有填充
      // gl.TRIANGLES 三角形,一个三角形被画出来,填充了颜色
      // gl.TRIANGLES_STRIP 三角带
      // g.TRIANGLE_FAN 三角扇
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    }

    main()

  </script>
</body>

</html>

3.3 旋转

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <div>
    <button onclick="main()">角度+</button>
    <div id="angle">

    </div>
  </div>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>
    var ANGLE = 0.0;
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色器
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'uniform float u_CosB, u_SinB;\n' +
        'void main() {\n' +
        '  gl_Position.x = a_Position.x * u_CosB - a_Position.y * u_SinB;\n' +
        '  gl_Position.y = a_Position.x * u_SinB - a_Position.y * u_CosB;\n' +
        '  gl_Position.z = a_Position.z;\n' +
        '  gl_Position.w = 1.0;\n' +
        // '  gl_Position = a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色器
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      var initVertexBuffers = function () {
        // 1.创建缓冲区对象
        // gl.dleteBuffer(buffer); 删除缓冲区对象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          throw new TypeError("创建缓冲区失败");
        }

        // 三角形
        var TRIANGLE = [
          0.0, 0.5,
          -0.5, -0.5,
          0.5, -0.5
        ]

        // 正方形
        var square = [
          -0.5, 0.5, // v0
          -0.5, -0.5, // v1
          0.5, 0.5, // v2
          0.5, -0.5 // v3
        ]

        var vertices = new Float32Array(TRIANGLE);

        // 2.绑定缓冲区对象到目标
        // gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT|ARRAY_BUFFER|buffer, buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 3.向缓冲区写入数据
        // gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER, data, usage);
        // usage gl.STATIC_DRAW | gl.STREAM_DRAW | gl.DYNAMIC_DRAW
        // gl.STATIC_DRAW: 只会想缓冲区对象写入一次数据,但需要绘制很多次
        // gl.STREAM_DRAW: 只会想缓冲区对象写入一次数据,然后绘制若干次
        // gl.DYNAMIC_DRAW: 会向缓冲区对象中多次写入数据,并绘制很多次
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        // 4.将缓冲区对象分配给变量
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          throw new TypeError("无法获取变量的存储位置")
        }

        // gl.vertexAttribPointer(location, size, type, normalize, stride, offset);
        // location 就是变量
        // size 可选值是 1-4,和vec4的赋值一样
        // type 表示类型,gl.FLOAT 浮点型,gl.INT(int32Array) 整形,...
        // normalize 传入true或false,表明是否将非浮点型的数据归一化到[1,0]或[-1,1]区间
        // stride 指定相邻两个顶点间的字节数,默认为0
        // offset 指定缓冲区对象中的偏移量(以字节为单位)即attribute变量从缓冲区中何处开始存储。如果从起始位置开始,offset设置为0
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        // 5.连接a_Poistion变量于分配给它缓冲区对象
        // 开启变量 gl.enableVertexAttribArray(location);
        gl.enableVertexAttribArray(a_Position);

        var radian = Math.PI * ANGLE / 180.0;
        var cosB = Math.cos(radian);
        var sinB = Math.sin(radian);
        var u_CosB = gl.getUniformLocation(gl.program, "u_CosB"); 
        var u_SinB = gl.getUniformLocation(gl.program, "u_SinB");

        document.getElementById("angle").innerHTML = ANGLE.toString();
        ANGLE+=1.0;

        if (!u_CosB || !u_SinB) {
          throw new TypeError("uniform 变量不存在")
        }
        gl.uniform1f(u_CosB, cosB);
        gl.uniform1f(u_SinB, sinB);

        return 3;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);


      // gl.POINTS 点
      // gl.LINES 线段,此时只画出一条线段(一次画一条)
      // gl.LINE_STRIP 线条,此时画出两条线,但是没有闭合线段
      // gl.LINE_LOOP 回路,一个三角形被画出来,但是都是线段的,没有填充
      // gl.TRIANGLES 三角形,一个三角形被画出来,填充了颜色
      // gl.TRIANGLES_STRIP 三角带
      // g.TRIANGLE_FAN 三角扇
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    }

    main()

  </script>
</body>

</html>

4、 矩阵旋转 + 动画

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <div>
    <button onclick="main()">角度+</button>
    <div id="angle">

    </div>
  </div>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script src="../lib/cuon-matrix.js"></script>
  <script>
    var ANGLE = 0.0;
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色器
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'uniform mat4 u_xformMatrix;\n' +
        'void main() {\n' +
        '  gl_Position = u_xformMatrix * a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色器
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      var initVertexBuffers = function () {
        // 1.创建缓冲区对象
        // gl.dleteBuffer(buffer); 删除缓冲区对象
        var vertexBuffer = gl.createBuffer();
        if (!vertexBuffer) {
          throw new TypeError("创建缓冲区失败");
        }

        // 三角形
        var TRIANGLE = [
          0.0, 0.5,
          -0.5, -0.5,
          0.5, -0.5
        ]

        // 正方形
        var square = [
          -0.5, 0.5, // v0
          -0.5, -0.5, // v1
          0.5, 0.5, // v2
          0.5, -0.5 // v3
        ]

        var vertices = new Float32Array(TRIANGLE);

        // 2.绑定缓冲区对象到目标
        // gl.bindBuffer(gl.ARRAY_BUFFER|gl.ELEMENT|ARRAY_BUFFER|buffer, buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
        // 3.向缓冲区写入数据
        // gl.bufferData(gl.ARRAY_BUFFER|gl.ELEMENT_ARRAY_BUFFER, data, usage);
        // usage gl.STATIC_DRAW | gl.STREAM_DRAW | gl.DYNAMIC_DRAW
        // gl.STATIC_DRAW: 只会想缓冲区对象写入一次数据,但需要绘制很多次
        // gl.STREAM_DRAW: 只会想缓冲区对象写入一次数据,然后绘制若干次
        // gl.DYNAMIC_DRAW: 会向缓冲区对象中多次写入数据,并绘制很多次
        gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
        // 4.将缓冲区对象分配给变量
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        if (a_Position < 0) {
          throw new TypeError("无法获取变量的存储位置")
        }

        // gl.vertexAttribPointer(location, size, type, normalize, stride, offset);
        // location 就是变量
        // size 可选值是 1-4,和vec4的赋值一样
        // type 表示类型,gl.FLOAT 浮点型,gl.INT(int32Array) 整形,...
        // normalize 传入true或false,表明是否将非浮点型的数据归一化到[1,0]或[-1,1]区间
        // stride 指定相邻两个顶点间的字节数,默认为0
        // offset 指定缓冲区对象中的偏移量(以字节为单位)即attribute变量从缓冲区中何处开始存储。如果从起始位置开始,offset设置为0
        gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
        // 5.连接a_Poistion变量于分配给它缓冲区对象
        // 开启变量 gl.enableVertexAttribArray(location);
        gl.enableVertexAttribArray(a_Position);

        var u_xformMatrix = gl.getUniformLocation(gl.program, "u_xformMatrix")
        // cuon-matrix.js 提供的 Matrix4 对象
        var xformMatrix = new Matrix4();

        xformMatrix.setRotate(ANGLE, 0, 0, 1);
        document.getElementById("angle").innerHTML = ANGLE.toString();
        ANGLE+=1;

        // gl.uniformMatrix4fv的第二个参数在webgl中固定是false
        gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements);

        return 3;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);


      // gl.POINTS 点
      // gl.LINES 线段,此时只画出一条线段(一次画一条)
      // gl.LINE_STRIP 线条,此时画出两条线,但是没有闭合线段
      // gl.LINE_LOOP 回路,一个三角形被画出来,但是都是线段的,没有填充
      // gl.TRIANGLES 三角形,一个三角形被画出来,填充了颜色
      // gl.TRIANGLES_STRIP 三角带
      // g.TRIANGLE_FAN 三角扇
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);
    }

    // 旋转速度,多少度1s
    var ANGLE_STEP = 1.0;
    // 上一次的时间
    var g_lost = new Date().getTime();
    function animate (__angle) {
      var now = Date.now();
      var elapsed = now - g_lost; // 经过了多长时间
      g_lost = now;

      var newAngle = ANGLE + (ANGLE_STEP * elapsed) / 1000;

      ANGLE = newAngle;
    }

    var tick = function() {
      main();
      animate();
      requestAnimationFrame(tick);
    }

    tick();

  </script>
</body>

</html>

画圆

方案一, 通过圆形的画点位,然后使用 g.TRIANGLE_FAN

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script>


function getXYByIndex(index, stepAngle) {
    let pai = 3.1415926;
    let circleRadius = 0.6;
    let angle = stepAngle * index;
    let angleInRadian = angle * pai / 180;
    let x = Math.cos(angleInRadian) * circleRadius;
    let y = Math.sin(angleInRadian) * circleRadius;
    return {x, y}
}

//生成顶点着色器需要的所有点的位置
function initVertexBuffers(gl) {
    let circleCenter = [0, 0];
    let n = 360;
    let stepAngle = 360 / n;
    let arr = [circleCenter[0], circleCenter[1]];
    for (let i = 0; i < n; i++) {
        let xy = getXYByIndex(i, stepAngle);
        let {x, y} = xy;
        arr.push(x);
        arr.push(y);
    }
    //如果没有下面3行代码,会出现一个缺口
    let xyRight = getXYByIndex(0, n);
    arr.push(xyRight.x);
    arr.push(xyRight.y);
    let verticesColors = new Float32Array(arr);
    let buffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
    let a_Position = gl.getAttribLocation(gl.program, "a_Position");
    gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(a_Position);
    return n + 2;
}



    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = 
        'attribute vec4 a_Position;\n' +
        'attribute float a_PointSize;\n' +
        'void main() {\n' +
        // vec4(x, y, z, w); x表示横向轴,y表示纵向轴,z轴, w齐次坐标(默认为1)
        // w是齐次坐标 齐次坐标(x, y, z, w) 等价于 (x/w, y/w, z/w);
        '  gl_Position = a_Position;\n' + // 设置点的位置
        '  gl_PointSize = a_PointSize;\n' +                    // 设置点的大小
        '}\n';

      // 片元着色气
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (a_PointSize < 0 || !u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      // vertexAttrib3f向变量attribute赋值
      // gl.vertexAttrib3f(location, v0, v1, v2)
      // 同类型方法有gl.vertexAttrib1f(location, v0)
      // 同类型方法有gl.vertexAttrib2f(location, v0, v1)
      // 同类型方法有gl.vertexAttrib4f(location, v0, v1, v2, v3)
      gl.vertexAttrib1f(a_PointSize, 10.0);

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      setShaders(gl);
      var n = initVertexBuffers(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);
      // gl.drawArrays(mode, first, count);
      // mode 表示绘制的方式
      // first 从那个顶点开始绘制
      // count 绘制几个顶点
      gl.drawArrays(gl.TRIANGLE_FAN, 0, n);
    }

    main()

  </script>
</body>

</html>

方案二,JavaScript中只算好等间隔的角度,通过角度在顶点着色器中计算出坐标

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <title>Clear canvas</title>
</head>

<body>
  <canvas id="webgl" width="400" height="400">
    Please use the browser supporting "canvas"
  </canvas>
  <script src="../lib/webgl-utils.js"></script>
  <script src="../lib/webgl-debug.js"></script>
  <script src="../lib/cuon-utils.js"></script>
  <script src="../lib/cuon-matrix.js"></script>
  <script>
    function initAngles(gl) {
      let n = 360;
      let step = 360 / n;
      let arr = [];
      for (let i = 0; i < n; i++) {
        arr.push(step * i);
      }

      var pai = 3.1415926

      for (let i = 0; i < arr.length; i++) {
        console.log(Math.cos(arr[i] * pai / 180.0), 
        Math.sin(arr[i] * pai / 180.0), 0.0, 1.0)
      }

      let verticesColors = new Float32Array(arr);
      let buffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
      gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);
      let a_Angle = gl.getAttribLocation(gl.program, "a_Angle");

      gl.vertexAttribPointer(a_Angle, 1, gl.FLOAT, false, 0, 0);
      gl.enableVertexAttribArray(a_Angle);

      var u_xformMatrix = gl.getUniformLocation(gl.program, "u_xformMatrix")
      // cuon-matrix.js 提供的 Matrix4 对象
      var xformMatrix = new Matrix4();

      xformMatrix.setScale(0.5, 0.5, 0)

      // gl.uniformMatrix4fv的第二个参数在webgl中固定是false
      gl.uniformMatrix4fv(u_xformMatrix, false, xformMatrix.elements);


      return n;
    }
    /**
    * 设置着色器
    */
    function setShaders(gl) {
      // 顶底着色气
      var VSHADER_SOURCE = `
#define pai 3.1415926
precision mediump float;
attribute float a_Angle;//圆上的某个点相对于Z轴的旋转角度
uniform mat4 u_xformMatrix;
void main()
{
    //下述的180.0,如果去掉小数点以及其后的0,那么就会报错
    float x=cos(a_Angle * pai / 180.0);
    float y=sin(a_Angle * pai / 180.0);
    gl_Position= u_xformMatrix * vec4(x, y, 0.0, 1.0);
}
`
      // 片元着色气
      var FSHADER_SOURCE =
        'precision mediump float;\n' +
        'uniform vec4 u_FragColor;\n' + // uniform变量
        'void main() {\n' +
        '  gl_FragColor = u_FragColor;\n' + // 设置颜色,rgba
        '}\n';

      if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
        throw new TypeError("未能初始化着色器");
      }
      // gl.getAttribLocation 方法是获取attribute变量的存储位置
      // var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
      // gl.getUniformLocation 获取uniform变量的存储位置
      var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor')

      if (!u_FragColor) {
        throw new TypeError("无法获取变量的存储位置")
      }

      gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1)
    }
    function main() {
      // 获取 <canvas> 元素
      var canvas = document.getElementById('webgl');
      // 获取 WebGL 绘图上下文
      var gl = getWebGLContext(canvas);
      if (!gl) {
        console.log('Failed to get the rendering context for WebGL');
        return;
      }

      setShaders(gl);
      var n = initAngles(gl);

      // 设置背景颜色
      gl.clearColor(0.0, 0.0, 0.0, 1.0);
      // 可以查询 gl.COLOR_BUFFER_BIT 的含义,以及clear方法的使用 https://developer.mozilla.org/zh-CN/docs/Web/API/WebGLRenderingContext/clear#%E5%8F%A5%E6%B3%95
      // gl.COLOR_BUFFER_BIT 颜色缓冲区
      // 清空颜色缓冲区
      gl.clear(gl.COLOR_BUFFER_BIT);
      // gl.drawArrays(mode, first, count);
      // mode 表示绘制的方式
      // first 从那个顶点开始绘制
      // count 绘制几个顶点
      gl.drawArrays(gl.TRIANGLE_FAN, 0, n);
    }

    main()

  </script>
</body>

</html>

方案三、

顶点着色器绘制一个和canvas重合的矩形,利用gl_FragCoord的坐标来对每个片元进行圆内筛选
让我觉得可以在片元着色器中来画圆的想法,是来自于片元着色器中的gl_FragCoord对象,gl_FragCoord.xyz可以读取每个像素的x、y、z坐标,拿到坐标,我就可以根据distance()方法来画圆,因为顶点坐标是骨架,再借鉴shaderToy的做法,实现思路,先在顶点着色器中画一个覆盖整个canvas的一个矩形,然后在片元着色器中来画圆

precision mediump float;
void main(){
    //canvas是一个400px*400px的矩形,我要在中心点画一个圆
    vec2 center=vec2(200, 200);
    //gl_FragCoord是一个二维坐标系,坐标原点位于canvas的左下角
    vec2 uv=gl_FragCoord.xy;
    //画一个半径为150px的圆
    bool isInCircle=distance(center, uv)<=150.0;
    if (isInCircle){
        gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
    } else {
        //如果没有下述语句,即使设置了gl.clearColor(),圆外底色会变成白色
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }
}