04. WEBGL2学习笔记:动画、二维矩阵

134 阅读4分钟

回顾一下上篇: # 03. WEBGL2学习笔记:平移、旋转、缩放

源码:03_translateAndRotate

1.动画

首先,做点调整,将缩放、平移、旋转去掉,修改后代码如下:

function main() {
  const gl = document.querySelector('#glCanvas').getContext('webgl2')
  if (!gl) {
    alert('WebGL2 not supported')
    return
  }

  const VERTEX_SHADER_SOURCE = `#version 300 es
  in vec2 a_position;

  void main() {
    gl_Position = vec4(a_position, 0, 1);
  }
`

  const FRAGMENT_SHADER_SOURCE = `#version 300 es
  precision highp float;
  uniform vec4 u_color;
  out vec4 a_color;
  void main() {
    a_color = u_color;
  }
`

  // 编译顶点着色器
  const shaderProgram = webglUtils.createProgramFromSources(gl, [VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE])

  // 创建顶点缓冲区
  const vertexBuffer = gl.createBuffer()////创建一个顶点缓冲区对象
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)////将缓冲区对象绑定到 WebGL 的`ARRAY_BUFFER`目标上

  //使用`bufferData`将我们要调整的坐标数据传输到`vertexBuffer`缓冲区中,数据类型为`Float32Array`,并指定了使用模式为`gl.STATIC_DRAW`,表示数据不会频繁改变。
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    // // 点的顶点数据
    // 10.0, 10.0,
    //
    // // 线条的顶点数据
    // 10.0, 10.0,
    // 550.0, 280.0,
    //
    // // 三角形的顶点数据
    // 100.0, 0.0,
    // 0.0, 100.0,
    // 200.0, 150.0,

    // 点的顶点数据
    0.0, 0.8,

    // 线条的顶点数据
    -0.5, -0.5,
    0.5, -0.5,

    // 三角形的顶点数据
    -0.5, 0.5,
    0.5, 0.5,
    0.0, 0.0
  ]), gl.STATIC_DRAW)


  // 获取位置属性
  const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position')
  const colorLocation = gl.getUniformLocation(shaderProgram, 'u_color');

  // 指定属性数据如何读取
  const vao = gl.createVertexArray()//创建一个新的顶点数组对象 (VAO)

  //将创建的 vao 绑定为当前的顶点数组对象
  gl.bindVertexArray(vao)

  // vertexAttribPointer:这个函数用于指定顶点属性数组如何解释存储在缓冲区中的数据
  //                      positionAttributeLocation:我们设定在顶点着色器的变量a_position的位置
  //                      2:表示每个顶点属性由两个分量组成(这里是 x 和 y 坐标)
  //                      gl.FLOAT:顶点属性数据类型,这里是浮点数。
  //                      false:是否标准化数据。对于浮点数类型,没有标准化。
  //                      0:stride,指定相邻两个顶点之间的字节距离。0 表示属性数据紧密地打包在一起。
  //                      0:offset,表示属性在缓冲区中起始位置的字节偏移量。这里为0,从缓冲区开头开始读取数据。
  gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0)

  //启用指定位置的顶点属性数组。
  gl.enableVertexAttribArray(positionAttributeLocation)

  drawScene()

  function drawScene() {
    webglUtils.resizeCanvasToDisplaySize(gl.canvas);

    // 清空画布
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
    gl.clearColor(0.0, 0.0, 0.0, 0.0)
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 执行指定的着色器
    gl.useProgram(shaderProgram)

    // 在绘制之前绑定顶点数组对象
    gl.bindVertexArray(vao)

    gl.uniform4fv(colorLocation, [
      Math.random(),
      Math.random(),
      Math.random(),
      1,
    ]);


    // 绘制点
    gl.drawArrays(gl.POINTS, 0, 1)

    // 绘制线条
    gl.drawArrays(gl.LINES, 1, 2)

    // 绘制三角形
    gl.drawArrays(gl.TRIANGLES, 3, 3)
  }
}

main()

运行,出现界面如下:

QQ_1725260386045.png

修改顶点着色器,添加矩阵:u_matrix

 const VERTEX_SHADER_SOURCE = `#version 300 es
  in vec2 a_position;
  uniform mat3 u_matrix;

  void main() {
    vec3 position = u_matrix * vec3(a_position, 1);
    gl_Position = vec4(position.xy, 0, 1);
  }
`

读取属性

const matrixLocation = gl.getUniformLocation(shaderProgram, "u_matrix");

在渲染层加一个setInterval和随机变量,用来做动画

let aa = Math.random();

drawScene()
setInterval(()=>{
  aa = Math.random();
  drawScene()
},10)

做矩阵渲染

// Set the matrix.
gl.uniformMatrix3fv(matrixLocation, false, new Float32Array([
  aa,
  0,
  0,
  0,
  -1,
  0,
  0,
  0.3,
  0
]));

效果如下: QQ_1725261012716.png 最终代码如下:

function main() {
  const gl = document.querySelector('#glCanvas').getContext('webgl2')
  if (!gl) {
    alert('WebGL2 not supported')
    return
  }

  const VERTEX_SHADER_SOURCE = `#version 300 es
  in vec2 a_position;
  uniform mat3 u_matrix;

  void main() {
    vec3 position = u_matrix * vec3(a_position, 1);
    gl_Position = vec4(position.xy, 0, 1);
  }
`

  const FRAGMENT_SHADER_SOURCE = `#version 300 es
  precision highp float;
  uniform vec4 u_color;
  out vec4 a_color;
  void main() {
    a_color = u_color;
  }
`

  // 编译顶点着色器
  const shaderProgram = webglUtils.createProgramFromSources(gl, [VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE])

  // 创建顶点缓冲区
  const vertexBuffer = gl.createBuffer()////创建一个顶点缓冲区对象
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)////将缓冲区对象绑定到 WebGL 的`ARRAY_BUFFER`目标上

  //使用`bufferData`将我们要调整的坐标数据传输到`vertexBuffer`缓冲区中,数据类型为`Float32Array`,并指定了使用模式为`gl.STATIC_DRAW`,表示数据不会频繁改变。
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    // // 点的顶点数据
    // 10.0, 10.0,
    //
    // // 线条的顶点数据
    // 10.0, 10.0,
    // 550.0, 280.0,
    //
    // // 三角形的顶点数据
    // 100.0, 0.0,
    // 0.0, 100.0,
    // 200.0, 150.0,

    // 点的顶点数据
    0.0, 0.8,

    // 线条的顶点数据
    -0.5, -0.5,
    0.5, -0.5,

    // 三角形的顶点数据
    -0.5, 0.5,
    0.5, 0.5,
    0.0, 0.0
  ]), gl.STATIC_DRAW)


  // 获取位置属性
  const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position')
  const colorLocation = gl.getUniformLocation(shaderProgram, 'u_color');
  const matrixLocation = gl.getUniformLocation(shaderProgram, "u_matrix");

  // 指定属性数据如何读取
  const vao = gl.createVertexArray()//创建一个新的顶点数组对象 (VAO)

  //将创建的 vao 绑定为当前的顶点数组对象
  gl.bindVertexArray(vao)

  // vertexAttribPointer:这个函数用于指定顶点属性数组如何解释存储在缓冲区中的数据
  //                      positionAttributeLocation:我们设定在顶点着色器的变量a_position的位置
  //                      2:表示每个顶点属性由两个分量组成(这里是 x 和 y 坐标)
  //                      gl.FLOAT:顶点属性数据类型,这里是浮点数。
  //                      false:是否标准化数据。对于浮点数类型,没有标准化。
  //                      0:stride,指定相邻两个顶点之间的字节距离。0 表示属性数据紧密地打包在一起。
  //                      0:offset,表示属性在缓冲区中起始位置的字节偏移量。这里为0,从缓冲区开头开始读取数据。
  gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0)

  //启用指定位置的顶点属性数组。
  gl.enableVertexAttribArray(positionAttributeLocation)

  let aa = Math.random();

  drawScene()
  setInterval(()=>{
    aa = Math.random();
    drawScene()
  },10)

  function drawScene() {
    webglUtils.resizeCanvasToDisplaySize(gl.canvas);

    // 清空画布
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
    gl.clearColor(0.0, 0.0, 0.0, 0.0)
    gl.clear(gl.COLOR_BUFFER_BIT)

    // 执行指定的着色器
    gl.useProgram(shaderProgram)

    // 在绘制之前绑定顶点数组对象
    gl.bindVertexArray(vao)

    gl.uniform4fv(colorLocation, [
      Math.random(),
      Math.random(),
      Math.random(),
      1,
    ]);

    // Set the matrix.
    gl.uniformMatrix3fv(matrixLocation, false, new Float32Array([
      aa,
      0,
      0,
      0,
      -1,
      0,
      0,
      0.3,
      0
    ]));

    // 绘制点
    gl.drawArrays(gl.POINTS, 0, 1)

    // 绘制线条
    gl.drawArrays(gl.LINES, 1, 2)

    // 绘制三角形
    gl.drawArrays(gl.TRIANGLES, 3, 3)
  }
}

main()

参考文献

webgl2fundamentals.org/webgl/lesso…