webgl instance 绘制

时间:2024-03-12 09:34:05

webgl instance 绘制

效果:
在这里插入图片描述

key1: 创建实例缓存
function createMesh() {
  for (let i = 0; i < NUM_CUBE; i++) {
    const angle = i * 2 * Math.PI / NUM_CUBE;
    const x = Math.sin(angle) * RADIUS;
    const y = 0;
    const z = Math.cos(angle) * RADIUS;

    cubes[i] = {
      scale: new THREE.Vector3(0.5, 0.5, 0.5),
      position: new THREE.Vector3(x, y, z),
      modelMatrix: new THREE.Matrix4(),
      rotation: new THREE.Euler(0, 0, 0),
      quaternion: new THREE.Quaternion(),
    };
  }

  // key1: 创建实例缓存
  modelMatrixData = new Float32Array(NUM_CUBE * 16);
  modelMatrixBuffer = WebGLVertex.createMatrix4x4(gl, {
    location: 3,
    data: modelMatrixData,
  });
}
key2: 在创建vao之后创建 实例缓存
// key2: 在创建vao之后创建 实例缓存
const geometry = getCubeGeometry(gl, createMesh)
/**
 * @export
 * @param {*} gl
 * @param {*} unbindVaoBefor 解绑vao之前的回调函数
 */
export function getCubeGeometry(gl, unbindVaoBefor) {
  const { attributes, index } = new THREE.BoxGeometry();

  const vao = gl.createVertexArray();
  gl.bindVertexArray(vao);

  WebGLVertex.createBuffer(gl, {
    data: attributes.position.array
  });

  WebGLVertex.configureAttribute(gl, {
    location: 0,
    count: attributes.position.itemSize,
    type: gl.FLOAT,
    stride: 0,
    offset: 0,
  });

  WebGLVertex.createBuffer(gl, {
    data: attributes.uv.array
  });

  WebGLVertex.configureAttribute(gl, {
    location: 1,
    count: attributes.uv.itemSize,
    type: gl.FLOAT,
    stride: 0,
    offset: 0,
  });

  WebGLVertex.createBuffer(gl, {
    data: attributes.normal.array
  });

  WebGLVertex.configureAttribute(gl, {
    location: 2,
    count: attributes.normal.itemSize,
    type: gl.FLOAT,
    stride: 0,
    offset: 0,
  });

  WebGLVertex.createBuffer(gl, {
    glBufferType: gl.ELEMENT_ARRAY_BUFFER,
    data: index.array
  });

  unbindVaoBefor && unbindVaoBefor();
  gl.bindVertexArray(null);

  return {
    vao,
    attributes,
    indexed: true,
    index: index.array
  };
}
key3: 指定实例数量
const { program, uniforms } = WebGLProgram.buildPrograms(gl, shaders).cube;
cubeCommand = new DrawCommand({
  gl,
  camera,
  geometry: new Geometry(geometry),
  program: program,
  uniforms: uniforms,
  // key3: 指定实例数量
  instanceCount: cubes.length,
  renderState: new RenderState({
    depthTest: {
      enabled: true,
    }
  }),
  uniformsData: {
    uTexture: {
      type: "t",
      value: sphereTexture
    },
  }
})
key4: 更新矩阵
function updateMesh() {
  for (let i = 0; i < cubes.length; ++i) {
    cubes[i].rotation.x += i * 0.01 * Math.random();
    cubes[i].rotation.y += i * 0.01 * Math.random();
    cubes[i].rotation.z += i * 0.01 * Math.random();

    cubes[i].quaternion.setFromEuler(cubes[i].rotation, false);
    cubes[i].modelMatrix.compose(cubes[i].position, 		   cubes[i].quaternion, cubes[i].scale);

    // key4: 更新矩阵
    modelMatrixData.set(cubes[i].modelMatrix.elements, i * 16);
    WebGLVertex.updateBuffer(gl, {
      buffer: modelMatrixBuffer,
      data: modelMatrixData,
    })
  }
}
循环渲染
function render() {
  updateCamera()
  updateMesh();

  gl.clearColor(0, 0, 0, 0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);

  gl.useProgram(program);
  cubeCommand.execute();
}