src/programs.js
function createUniformBlockSpecFromProgram(gl, program) {
  const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  const uniformData = [];
  const uniformIndices = [];

  for (let ii = 0; ii < numUniforms; ++ii) {
    uniformIndices.push(ii);
    uniformData.push({});
    const uniformInfo = gl.getActiveUniform(program, ii);
    if (isBuiltIn(uniformInfo)) {
      break;
    }
    // REMOVE [0]?
    uniformData[ii].name = uniformInfo.name;
  }

  [
    [ "UNIFORM_TYPE", "type" ],
    [ "UNIFORM_SIZE", "size" ],  // num elements
    [ "UNIFORM_BLOCK_INDEX", "blockNdx" ],
    [ "UNIFORM_OFFSET", "offset", ],
  ].forEach(function(pair) {
    const pname = pair[0];
    const key = pair[1];
    gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) {
      uniformData[ndx][key] = value;
    });
  });

  const blockSpecs = {};

  const numUniformBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  for (let ii = 0; ii < numUniformBlocks; ++ii) {
    const name = gl.getActiveUniformBlockName(program, ii);
    const blockSpec = {
      index: ii,
      usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER),
      usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER),
      size: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_DATA_SIZE),
      uniformIndices: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES),
    };
    blockSpec.used = blockSpec.usedByVertexSahder || blockSpec.usedByFragmentShader;
    blockSpecs[name] = blockSpec;
  }

  return {
    blockSpecs: blockSpecs,
    uniformData: uniformData,
  };
}
function createUniformBlockSpecFromProgram(gl, program) {
  const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  const uniformData = [];
  const uniformIndices = [];

  for (let ii = 0; ii < numUniforms; ++ii) {
    uniformIndices.push(ii);
    uniformData.push({});
    const uniformInfo = gl.getActiveUniform(program, ii);
    if (isBuiltIn(uniformInfo)) {
      break;
    }
    // REMOVE [0]?
    uniformData[ii].name = uniformInfo.name;
  }

  [
    [ "UNIFORM_TYPE", "type" ],
    [ "UNIFORM_SIZE", "size" ],  // num elements
    [ "UNIFORM_BLOCK_INDEX", "blockNdx" ],
    [ "UNIFORM_OFFSET", "offset", ],
  ].forEach(function(pair) {
    const pname = pair[0];
    const key = pair[1];
    gl.getActiveUniforms(program, uniformIndices, gl[pname]).forEach(function(value, ndx) {
      uniformData[ndx][key] = value;
    });
  });

  const blockSpecs = {};

  const numUniformBlocks = gl.getProgramParameter(program, gl.ACTIVE_UNIFORM_BLOCKS);
  for (let ii = 0; ii < numUniformBlocks; ++ii) {
    const name = gl.getActiveUniformBlockName(program, ii);
    const blockSpec = {
      index: ii,
      usedByVertexShader: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER),
      usedByFragmentShader: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER),
      size: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_DATA_SIZE),
      uniformIndices: gl.getActiveUniformBlockParameter(program, ii, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES),
    };
    blockSpec.used = blockSpec.usedByVertexSahder || blockSpec.usedByFragmentShader;
    blockSpecs[name] = blockSpec;
  }

  return {
    blockSpecs: blockSpecs,
    uniformData: uniformData,
  };
}
function createUniformBlockSpecFromProgram ( gl , program ) { const numUniforms = gl . getProgramParameter ( program , gl . ACTIVE_UNIFORMS ) ; const uniformData = [ ] ; const uniformIndices = [ ] ; for ( let ii = 0 ; ii < numUniforms ; ++ ii ) { uniformIndices . push ( ii ) ; uniformData . push ( { } ) ; const uniformInfo = gl . getActiveUniform ( program , ii ) ; if ( isBuiltIn ( uniformInfo ) ) { break ; } // REMOVE [0]? uniformData [ ii ] . name = uniformInfo . name ; } [ [ "UNIFORM_TYPE" , "type" ] , [ "UNIFORM_SIZE" , "size" ] , // num elements [ "UNIFORM_BLOCK_INDEX" , "blockNdx" ] , [ "UNIFORM_OFFSET" , "offset" , ] , ] . forEach ( function ( pair ) { const pname = pair [ 0 ] ; const key = pair [ 1 ] ; gl . getActiveUniforms ( program , uniformIndices , gl [ pname ] ) . forEach ( function ( value , ndx ) { uniformData [ ndx ] [ key ] = value ; } ) ; } ) ; const blockSpecs = { } ; const numUniformBlocks = gl . getProgramParameter ( program , gl . ACTIVE_UNIFORM_BLOCKS ) ; for ( let ii = 0 ; ii < numUniformBlocks ; ++ ii ) { const name = gl . getActiveUniformBlockName ( program , ii ) ; const blockSpec = { index : ii , usedByVertexShader : gl . getActiveUniformBlockParameter ( program , ii , gl . UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER ) , usedByFragmentShader : gl . getActiveUniformBlockParameter ( program , ii , gl . UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER ) , size : gl . getActiveUniformBlockParameter ( program , ii , gl . UNIFORM_BLOCK_DATA_SIZE ) , uniformIndices : gl . getActiveUniformBlockParameter ( program , ii , gl . UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES ) , } ; blockSpec . used = blockSpec . usedByVertexSahder || blockSpec . usedByFragmentShader ; blockSpecs [ name ] = blockSpec ; } return { blockSpecs : blockSpecs , uniformData : uniformData , } ; }
A `UniformBlockSpec` represents the data needed to create and bind
UniformBlockObjects for a given program

@typedef {Object} UniformBlockSpec
@property {Object.<string, module:twgl.BlockSpec> blockSpecs The BlockSpec for each block by block name
@property {UniformData[]} uniformData An array of data for each uniform by uniform index.
@memberOf module:twgl
 
Creates a UniformBlockSpec for the given program.

A UniformBlockSpec represents the data needed to create and bind
UniformBlockObjects

@param {WebGL2RenderingContext} gl A WebGL2 Rendering Context
@param {WebGLProgram} program A WebGLProgram for a successfully linked program
@return {module:twgl.UniformBlockSpec} The created UniformBlockSpec
@memberOf module:twgl/programs
A UniformBlockSpec represents the data needed to create and bind UniformBlockObjects for a given program