WebGL笔记:绘制矩形面的几种方式以及封装封装多边形对象来绘制不同图形

绘制矩形面

  • 可以绘制的面只有三角面,要绘制矩形面的话,只能用两个三角形去拼

1 ) 使用 三角带 TRIANGLE_STRIP 绘制矩形

WebGL笔记:绘制矩形面的几种方式以及封装封装多边形对象来绘制不同图形_第1张图片
  • 回顾一下之前的规律:

    • 第一个三角形:v0>v1>v2
    • 第偶数个三角形:以上一个三角形的第二条边+下一个点为基础,以和第二条边相反的方向绘制三角形
    • 第奇数个三角形:以上一个三角形的第三条边+下一个点为基础,以和第二条边相反的方向绘制三角形
  • 关键顶点绘制数据

    const vertices = new Float32Array([
        -0.2, 0.2,
        -0.2,-0.2,
        0.2, 0.2,
        0.2,-0.2,
    ])
    
  • 绘制: gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

2 ) 使用 三角带 TRIANGLE_FAN 绘制矩形


  • 回顾一下之前的规律:

    • v0>v1>v2: 以上一个三角形的第三条边+下一个点为基础,按照和第三条边相反的顺序,绘制三角形
    • v0>v2>v3: 同上
    • v0>v3>v4: 同上
    • v0>v4>v5: 同上
  • 基于此,设计顶点关键数据

    const vertices = new Float32Array([
        -0.2, -0.2,
        0.2, -0.2,
        0.2, 0.2,
        -0.2, 0.2
    ])
    
  • 绘制: gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)

3 )使用独立三角形,绘制矩形


  • 绘制规律

    • 这里就是普通的三角形,画了2个,需要6个点
    • 上面两个面的绘制顺序是: v0>v1>v2,v3>v4>v5
  • 顶点关键数据

    const vertices = new Float32Array([
        -0.2, 0.2,
        -0.2, -0.2,
        0.2, 0.2,
        0.2, 0.2,
        -0.2, -0.2,
        0.2, -0.2
    ])
    

可以根据自己的需求,绘制各种各样的图形

封装多边形对象

1 )封装一个Poly 对象,用于绘制多边形

const defAttr = () => ({
  gl: null,
  vertices: [],
  geoData: [],
  size: 2,
  attrName: 'a_Position',
  count: 0,
  types: ['POINTS'],
})

export default class Poly {
  constructor(attr) {
    Object.assign(this,defAttr(),attr)
    this.init()
  }
  init() {
    const { attrName, size, gl } = this;
    if(!gl) return
    const vertexBuffer = gl.createBuffer()
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
    this.updateBuffer()
    const a_Position = gl.getAttribLocation(gl.program,attrName)
    gl.vertexAttribPointer(a_Position, size, gl.FLOAT, false, 0, 0)
    gl.enableVertexAttribArray(a_Position)
  }
  addVertice(...params) {
    this.vertices.push(...params)
    this.updateBuffer()
  }
  popVertice() {
    const { vertices, size }=this
    const len = vertices.length
    vertices.splice(len-size,len)
    this.updateCount()
  }
  setVertice(ind,...params) {
    const { vertices, size }=this
    const i = ind * size
    params.forEach((param,paramInd) => {
      vertices[i+paramInd] = param
    })
  }
  updateBuffer() {
    const { gl,vertices } = this
    this.updateCount()
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)
  }
  updateCount() {
    this.count = this.vertices.length / this.size
  }
  updateVertices(params) {
    const { geoData } = this
    const vertices = []
    geoData.forEach(data => {
      params.forEach(key => {
        vertices.push(data[key])
      })
    })
    this.vertices=vertices
  }
  draw(types = this.types) {
    const { gl, count } = this
    for(let type of types) {
      gl.drawArrays(gl[type],0,count);
    }
  }
}
  • 属性

    • gl webgl上下文对象
    • vertices 顶点数据集合,在被赋值的时候会做两件事
      • 更新count 顶点数量,数据运算尽量不放渲染方法里
      • 向缓冲区内写入顶点数据
    • geoData 模型数据,对象数组,可解析出 vertices 顶点数据
    • size 顶点分量的数目
    • positionName 代表顶点位置的attribute 变量名
    • count 顶点数量
    • types 绘图方式,可以用多种方式绘图
  • 方法

    • init() 初始化方法,建立缓冲对象,并将其绑定到webgl 上下文对象上,然后向其中写入顶点数据。将缓冲对象交给attribute变量,并开启attribute 变量的批处理功能。
    • addVertice() 添加顶点
    • popVertice() 删除最后一个顶点
    • setVertice() 根据索引位置设置顶点
    • updateBuffer() 更新缓冲区数据,同时更新顶点数量
    • updateCount() 更新顶点数量
    • updateVertices() 基于geoData 解析出vetices 数据
    • draw() 绘图方法

2 )应用1

const poly = new Poly({
  gl,
  vertices:[0, 0.2]
})

poly.draw(['POINTS'])

setTimeout(()=>{
  poly.addVertice(-0.2, -0.1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  poly.draw(['POINTS'])
}, 1000)

setTimeout(()=>{
  gl.clear(gl.COLOR_BUFFER_BIT);
  poly.draw(['POINTS','LINE_STRIP'])
}, 2000)

3 )应用2

// 实例化多边形
const poly = new Poly({
    gl,
    types:['POINTS','LINE_STRIP']
})

// 鼠标点击事件
canvas.addEventListener("click", (event) => {
    const { x,y } = getMousePosInWebgl(event, canvas);
    poly.addVertice(x,y);
    gl.clear(gl.COLOR_BUFFER_BIT);
    poly.draw();
});

你可能感兴趣的:(Canvas,Webgl,Three.js,webgl)