Desde mirar algunos ejemplos diferentes en la naturaleza, parece que la carga de datos en un búfer, para su uso como un tampón uniforme, hace la siguiente secuencia:

  1. bindBuffer ()
  2. bufferData ()
  3. BindBufffer () - Con NULL, es decir "" Desbrindar "
  4. Bindbuffferrange ()

¿Cuál es el propósito del Paso 3?

0
davidkomer 26 jun. 2019 a las 21:37

1 respuesta

La mejor respuesta

No necesitas hacerlo en ese orden.

El ejemplo más simple:

'use strict';

const vs = `#version 300 es
void main() {
  gl_PointSize = 128.0;
  gl_Position = vec4(0, 0, 0, 1);
}
`;
const fs = `#version 300 es
precision mediump float;

uniform Color {
  vec4 u_color;
};

out vec4 outColor;

void main() {
  outColor = u_color;
}
`;

const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need webgl2');
const program = twgl.createProgram(gl, [vs, fs]);

const color = new Float32Array([1, 0.5, 0.7, 1]);
const buffer = gl.createBuffer();

// there's only 1 so I believe it's safe to guess index 0
const uniformBlockIndex = 0;
const uniformBlockBinding = 0;
gl.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);


// at render time
gl.useProgram(program);

// for each block
{
  const uniformBlockBufferOffset = 0;
  const uniformBlockBufferOffsetByteLength = 16;  // 4 floats
  gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding, buffer, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);

  // set the data
  gl.bufferData(gl.UNIFORM_BUFFER, color, gl.DYNAMIC_DRAW);
}


gl.drawArrays(gl.POINTS, 0, 1);
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

Si desea ver un ejemplo complejo, puede cavar a través de este ejemplo . Consulta todos los datos sobre tampones uniformes cuando se crea el programa. Cuántos hay, cuáles son sus nombres, qué uniformes utilizan, cuáles son los tipos de esos uniformes. Esto sucede cuando llame twgl.createProgramInfo que puede Mire dentro y vea esa información se crea en createUniformBlockSpecFromProgram

Luego, luego, utilizando la especificación de bloque, puede crear un TypDarray con las vistas de PREMADE en esa matriz para todos los uniformes llamando twgl.createUniformBlockInfo

const ubi = twgl.createUniformBlockInfo(...)

Podría establecer los valores uniformes en el TypDarray a través de las vistas directamente utilizando

ubi.uniforms.nameOfUniform.set(newValue)

Pero eso sería quebradizo, ya que los bloques pueden optimizarse mientras se depuran, por lo que, en su lugar, puede usar los menos frágiles

twgl.setBlockUniforms(ubi, {nameOfUniform: newValue});

Cuando realmente desea que los datos en TypDarray se suban a la GPU que llama

twgl.setUniformBlock(...);

Lo que ambos unen el bloque uniforme a su unión asignada y cargan los datos a la GPU.

Si solo desea unir un bloque existente (no hay necesidad de cargar datos nuevos), entonces

twgl.bindUniformBlock(gl, programInfo, ubi);

Sin embargo, el patrón es como lo ves en el ejemplo.

  1. bindbuffferrange
  2. bufferdata

BindBuffRRANGE ya se une al búfer para que podamos usar esa obligación para cargar los datos.

Prueba (nonmueros)

'use strict';

const vs = `#version 300 es
void main() {
  gl_PointSize = 128.0;
  gl_Position = vec4(0, 0, 0, 1);
}
`;
const fs = `#version 300 es
precision mediump float;

uniform Color1 {
  vec4 u_color1;
};
uniform Color2 {
  vec4 u_color2;
};

out vec4 outColor;

void main() {
  outColor = u_color1 + u_color2;
}
`;

const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need webgl2');
const program = twgl.createProgram(gl, [vs, fs]);

const color1 = new Float32Array([1, 0, 0, 1]);
const buffer1 = gl.createBuffer();
const color2 = new Float32Array([0, 0, 1, 1]);
const buffer2 = gl.createBuffer();

// there's only 2 and they are the same format so we don't really
// care which is which to see the results.
const uniformBlockIndex = 0;
const uniformBlockBinding = 0;
gl.uniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
gl.uniformBlockBinding(program, uniformBlockIndex + 1, uniformBlockBinding + 1);


// at render time
gl.useProgram(program);

{
  const uniformBlockBufferOffset = 0;
  const uniformBlockBufferOffsetByteLength = 16;  // 4 floats
  gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding, buffer1, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);

  // set the data
  gl.bufferData(gl.UNIFORM_BUFFER, color1, gl.DYNAMIC_DRAW);
  
  
  gl.bindBufferRange(gl.UNIFORM_BUFFER, uniformBlockBinding + 1, buffer2, uniformBlockBufferOffset, uniformBlockBufferOffsetByteLength);

  // set the data
  gl.bufferData(gl.UNIFORM_BUFFER, color2, gl.DYNAMIC_DRAW);
}


gl.drawArrays(gl.POINTS, 0, 1);
<canvas></canvas>
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>

El ejemplo anterior muestra bindBufferRange hace 2 cosas.

  1. Se une al búfer al punto de enlace UNIFORM_BUFFER
  2. Se une a una parte del tampón al índice de tampón uniforme.

Sabemos que funcionó porque el resultado es púrpura. Si no funcionaba, sería rojo o azul.

De la sección OpenGL ES 3.0 SECTOR 2.10.1.1 en relación a bindBufferRange

Cada objetivo representa una matriz indexada de puntos de enlace de objetos de búfer, también Como un solo punto de enlace general que puede ser utilizado por otras funciones de manipulación de objetos de tampón

1
gman 27 jun. 2019 a las 04:47