src/programs.js
function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) {
  const blockSpecs = uniformBlockSpec.blockSpecs;
  const uniformData = uniformBlockSpec.uniformData;
  const blockSpec = blockSpecs[blockName];
  if (!blockSpec) {
    warn("no uniform block object named:", blockName);
    return {
      name: blockName,
      uniforms: {},
    };
  }
  const array = new ArrayBuffer(blockSpec.size);
  const buffer = gl.createBuffer();
  const uniformBufferIndex = blockSpec.index;
  gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
  gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex);

  let prefix = blockName + ".";
  if (arraySuffixRE.test(prefix)) {
    prefix = prefix.replace(arraySuffixRE, ".");
  }
  const uniforms = {};
  blockSpec.uniformIndices.forEach(function(uniformNdx) {
    const data = uniformData[uniformNdx];
    const typeInfo = typeMap[data.type];
    const Type = typeInfo.Type;
    const length = data.size * typeInfo.size;
    let name = data.name;
    if (name.substr(0, prefix.length) === prefix) {
      name = name.substr(prefix.length);
    }
    uniforms[name] = new Type(array, data.offset, length / Type.BYTES_PER_ELEMENT);
  });
  return {
    name: blockName,
    array: array,
    asFloat: new Float32Array(array),  // for debugging
    buffer: buffer,
    uniforms: uniforms,
  };
}
function createUniformBlockInfoFromProgram(gl, program, uniformBlockSpec, blockName) {
  const blockSpecs = uniformBlockSpec.blockSpecs;
  const uniformData = uniformBlockSpec.uniformData;
  const blockSpec = blockSpecs[blockName];
  if (!blockSpec) {
    warn("no uniform block object named:", blockName);
    return {
      name: blockName,
      uniforms: {},
    };
  }
  const array = new ArrayBuffer(blockSpec.size);
  const buffer = gl.createBuffer();
  const uniformBufferIndex = blockSpec.index;
  gl.bindBuffer(gl.UNIFORM_BUFFER, buffer);
  gl.uniformBlockBinding(program, blockSpec.index, uniformBufferIndex);

  let prefix = blockName + ".";
  if (arraySuffixRE.test(prefix)) {
    prefix = prefix.replace(arraySuffixRE, ".");
  }
  const uniforms = {};
  blockSpec.uniformIndices.forEach(function(uniformNdx) {
    const data = uniformData[uniformNdx];
    const typeInfo = typeMap[data.type];
    const Type = typeInfo.Type;
    const length = data.size * typeInfo.size;
    let name = data.name;
    if (name.substr(0, prefix.length) === prefix) {
      name = name.substr(prefix.length);
    }
    uniforms[name] = new Type(array, data.offset, length / Type.BYTES_PER_ELEMENT);
  });
  return {
    name: blockName,
    array: array,
    asFloat: new Float32Array(array),  // for debugging
    buffer: buffer,
    uniforms: uniforms,
  };
}
function createUniformBlockInfoFromProgram ( gl , program , uniformBlockSpec , blockName ) { const blockSpecs = uniformBlockSpec . blockSpecs ; const uniformData = uniformBlockSpec . uniformData ; const blockSpec = blockSpecs [ blockName ] ; if ( ! blockSpec ) { warn ( "no uniform block object named:" , blockName ) ; return { name : blockName , uniforms : { } , } ; } const array = new ArrayBuffer ( blockSpec . size ) ; const buffer = gl . createBuffer ( ) ; const uniformBufferIndex = blockSpec . index ; gl . bindBuffer ( gl . UNIFORM_BUFFER , buffer ) ; gl . uniformBlockBinding ( program , blockSpec . index , uniformBufferIndex ) ; let prefix = blockName + "." ; if ( arraySuffixRE . test ( prefix ) ) { prefix = prefix . replace ( arraySuffixRE , "." ) ; } const uniforms = { } ; blockSpec . uniformIndices . forEach ( function ( uniformNdx ) { const data = uniformData [ uniformNdx ] ; const typeInfo = typeMap [ data . type ] ; const Type = typeInfo . Type ; const length = data . size * typeInfo . size ; let name = data . name ; if ( name . substr ( 0 , prefix . length ) === prefix ) { name = name . substr ( prefix . length ) ; } uniforms [ name ] = new Type ( array , data . offset , length / Type . BYTES_PER_ELEMENT ) ; } ) ; return { name : blockName , array : array , asFloat : new Float32Array ( array ) , // for debugging buffer : buffer , uniforms : uniforms , } ; }
Represents a UniformBlockObject including an ArrayBuffer with all the uniform values
and a corresponding WebGLBuffer to hold those values on the GPU

@typedef {Object} UniformBlockInfo
@property {string} name The name of the block
@property {ArrayBuffer} array The array buffer that contains the uniform values
@property {Float32Array} asFloat A float view on the array buffer. This is useful
inspecting the contents of the buffer in the debugger.
@property {WebGLBuffer} buffer A WebGL buffer that will hold a copy of the uniform values for rendering.
@property {number} [offset] offset into buffer
@property {Object.<string, ArrayBufferView>} uniforms A uniform name to ArrayBufferView map.
each Uniform has a correctly typed `ArrayBufferView` into array at the correct offset
and length of that uniform. So for example a float uniform would have a 1 float `Float32Array`
view. A single mat4 would have a 16 element `Float32Array` view. An ivec2 would have an
`Int32Array` view, etc.
@memberOf module:twgl
 
Creates a `UniformBlockInfo` for the specified block

Note: **If the blockName matches no existing blocks a warning is printed to the console and a dummy
`UniformBlockInfo` is returned**. This is because when debugging GLSL
it is common to comment out large portions of a shader or for example set
the final output to a constant. When that happens blocks get optimized out.
If this function did not create dummy blocks your code would crash when debugging.

@param {WebGL2RenderingContext} gl A WebGL2RenderingContext
@param {WebGLProgram} program A WebGLProgram
@param {module:twgl.UniformBlockSpec} uinformBlockSpec. A UniformBlockSpec as returned
from {@link module:twgl.createUniformBlockSpecFromProgram}.
@param {string} blockName The name of the block.
@return {module:twgl.UniformBlockInfo} The created UniformBlockInfo
@memberOf module:twgl/programs
Represents a UniformBlockObject including an ArrayBuffer with all the uniform values and a corresponding WebGLBuffer to hold those values on the GPU