Как удалить gl.bufferData для рисования множества спрайтов с помощью пакетного рендера? - PullRequest
0 голосов
/ 22 марта 2020

Я хочу создать пакетное средство рендеринга, в котором я помещаю несколько sh сведений о себе (вершины, uvs, индексы) в один буфер и рисую их одним вызовом gl.drawElements.

Эти сетки могут изменяя положение и масштаб, эти преобразования влияют на данные вершин, тем самым обновляя буфер вершин. Это означает дополнительный вызов gl.bindBuffer.

Я не смог сделать рабочую версию, но прежде всего у меня возникла проблема с производительностью gl.bindBuffer, она вызывается при каждом рендеринге и занимает много времени, в этой функции:

function renderFunction() {
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), drawType);

    this.renderBatched(...);
}


this.renderBatched = (drawInfo, uniformArgs, indices) => {
  const cookUniforms = Object.keys(drawInfo.uniforms).map(key => {
    let setter = drawInfo.uniforms[key];
    let args = uniformArgs[key];
    return () => {
      if (!args) {
        throw new Error("undefined uniform " + key);
      }
      setter(...args);
    };
  });

  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.clear(gl.COLOR_BUFFER_BIT);

  let {
    program,
    uniforms,
    textureInfos,
    bufferInfos
  } = drawInfo;

  gl.useProgram(program);

  bufferInfos.forEach(({
    buffer,
    size,
    index
  }) => {
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

    gl.vertexAttribPointer(index,
                           size,
                           gl.FLOAT,
                           false,
                           0,
                           0);
    gl.enableVertexAttribArray(index);

  });

  let indexBuffer = gl.createBuffer();

  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

  // https://stackoverflow.com/questions/38948908/vbo-and-ebo-state-in-webgl
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
                new Uint16Array(indices),
                gl.STATIC_DRAW);


  textureInfos.forEach(({ glTexture, index }) => {
    gl.uniform1i(index, 0);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, glTexture);
  });


  cookUniforms.forEach(_ => _());

  let numElements = indices.length;

  gl.drawElements(gl.TRIANGLES, numElements, gl.UNSIGNED_SHORT, 0);
};

Так что мне нужно исключить вызовы gl.bufferData вместо каждого рендера, но что мне делать, если данные буфера изменяются при преобразовании сеток.

Я смотрю вверх по источнику PIXI, но я ничего не понимаю.

В данный момент меня не волнуют текстуры, я хочу рисовать на экране много движущихся квадов без потери производительности.

...