zc

webGL

@

基础使用

    const ctx =document.getElementById('canvas').getContext('webgl');
    ctx.clearColor(0.0, 0.0, 0.0, 1.0); //清空颜色
    ctx.clear(ctx.COLOR_BUFFER_BIT); //
    //.COLOR_BUFFER_BIT 清空颜色缓存   ctx.clearColor(0.0, 0.0, 0.0, 1.0)
    //DEPTH_BUFFER_BIT 清空深度缓冲区 搭配 gl.clearDepth(1.0)
    //STENCIL_BUFFER_BIT 清空模板缓冲区 搭配 gl.clearStencil(0)

基础着色器封装

function initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE) {
  const vertexShader = gl.createShader(gl.VERTEX_SHADER); //创建顶点着色器
  const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); // 创建片元着色器

  gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE) // 指定顶点着色器的源码
  gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE) // 指定片元着色器的源码

  // 编译着色器
  gl.compileShader(vertexShader)
  gl.compileShader(fragmentShader)

  // 创建一个程序对象
  const program = gl.createProgram();

  gl.attachShader(program, vertexShader) //关联着色器
  gl.attachShader(program, fragmentShader)//关联着色器

  gl.linkProgram(program)//关联程序对象

  gl.useProgram(program)//使用程序对象

  return program;
}

创建变量并使用attribute变量和 uniform变量

  const ctx = document.getElementById('canvas')

  const gl = ctx.getContext('webgl')

  // 创建着色器源码
  const VERTEX_SHADER_SOURCE = `
    // 只传递顶点数据
    attribute vec4 aPosition; //创建aPosition变量
    void main() {
      gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0)
      gl_PointSize = 30.0;
    }
  `; // 顶点着色器

  const FRAGMENT_SHADER_SOURCE = `
   precision mediump float;  //指定精度
     uniform vec2 uColor;
    void main() {
      gl_FragColor = vec4(1.0,0.0,0.0,1.0);
    }
  `; // 片元着色器

  const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)

  const aPosition = gl.getAttribLocation(program, 'aPosition'); //获取aPosition变量
  const uColor = gl.getUniformLocation(program, 'uColor') //获取uColor变量
  // gl.vertexAttrib4f(aPosition, 0.5,0.5,0.0,1.0)
  // gl.vertexAttrib3f(aPosition, 0.5,0.5,0.0)
  // gl.vertexAttrib2f(aPosition, 0.5,0.5)

  let x = 0;
  setInterval(() => {
    x += 0.1;
    if (x > 1.0) {
      x = 0;
    }
    gl.vertexAttrib1f(aPosition, x) //修改值

    gl.drawArrays(gl.POINTS, 0, 1); //重新绘制
  }, 200)

点击绘制事件

  ctx.onclick = function(ev) {
    // 坐标
    const x = ev.clientX //获取点击坐标
    const y = ev.clientY//获取点击坐标

    const domPosition = ev.target.getBoundingClientRect();

    const domx = x - domPosition.left //计算出canvas坐标
    const domy = y - domPosition.top;

    const halfWidth = ctx.offsetWidth / 2
    const halfHeight = ctx.offsetHeight / 2

    const clickX = (domx - halfWidth) / halfWidth //计算出webgl坐标
    const clickY = (halfHeight - domy) / halfHeight

    points.push({
      clickX, clickY
    })

    for (let i = 0; i < points.length; i++) {
      gl.vertexAttrib2f(aPosition, points[i].clickX, points[i].clickY) //设置位置
  gl.uniform2f(uColor, points[i].clickX, points[i].clickY)//设置颜色
      gl.drawArrays(gl.POINTS, 0, 1);
    }
  }

着色器使用

const ctx = document.getElementById('canvas')

const gl = ctx.getContext('webgl')

// 创建着色器源码
const VERTEX_SHADER_SOURCE = `
  // 只传递顶点数据
  attribute vec4 aPosition; //创建aPosition变量
  attribute float aSize;
  void main() {
    gl_Position = aPosition; // vec4(0.0,0.0,0.0,1.0)
    gl_PointSize = aSize;
  }
`; // 顶点着色器

const FRAGMENT_SHADER_SOURCE = `
 precision mediump float;  //指定精度
   uniform vec2 uColor;
  void main() {
    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
  }
`; // 片元着色器

const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)

const aPosition = gl.getAttribLocation(program, 'aPosition'); //获取aPosition变量
const uColor = gl.getUniformLocation(program, 'uColor') //获取uColor变量
const aSize = gl.getAttribLocation(program, 'aSize')
// gl.vertexAttrib4f(aPosition, 0.5,0.5,0.0,1.0)
// gl.vertexAttrib3f(aPosition, 0.5,0.5,0.0)
// gl.vertexAttrib2f(aPosition, 0.5,0.5)

const points = new Float32Array([
    -0.5, -0.5, 30.0,
     0.5, -0.5, 30.0,
     0.0,  0.5, 20.0,
])

const buffer = gl.createBuffer(); //创建缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); //将缓冲区对象绑定到目标 
//gl.ARRAY_BUFFER 表示缓冲区储存的是顶点的数据
//gl.ElEMENT_ARRAY_BUFFER 表示缓冲区储存的是顶点的索引值
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW); //向缓冲区对象写入数据
//gl.STATIC_DRAW 
//数据不会或几乎不会改变。
//gl.STREAM_DRAW
//数据每次绘制时都会改变。
//gl.DYNAMIC_DRAW
//数据每次绘制时都会改变,并且绘制之间还会改变。
const BYTES = points.BYTES_PER_ELEMENT
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, BYTES * 3, 0); //将缓冲区对象分配给aPosition变量
gl.vertexAttribPointer(aSize, 1, gl.FLOAT, false, BYTES * 3,  BYTES * 2); 
// gl.vertexAttribPointer(
//     aPosition, //
//     指定每个顶点所使用数据的个数,
//      指定数据格式, gl.FlOAT gl.SHORT短整型 gl.UNSIGNED_BYTE 无符号字节 gl.INT整型 gl.UNSIGNED_SHORT无符号短整型 gl.UNSIGNED_INT无符号整型
//       是否将数据归一化到[0,1][-1,1 ]这个区间
//      指定连续两个顶点之间的字节数(如果是非整数数据,需要指定字节数),
//      数据偏移量
//       )
gl.enableVertexAttribArray(aPosition); //连接aPosition变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(aSize); //连接aPosition变量与分配给它的缓冲区对象
gl.drawArrays(gl.POINTS, 0, 3); //重新绘制(绘制什么图形,从第几个开始绘制,绘制个数)
//gl.LINE_LOOP 绘制闭合线段
//gl.TRIANGLES 绘制填充矩形

gl.drawArrays

码字很辛苦,转载请注明来自zcc_blog《webGL》

评论