2

when I write uniformBuffer in shader like this.

uniform Material {
    uniform vec4 u_DiffuseColor;
    uniform vec4 u_TilingOffset;
    uniform vec3 u_MaterialSpecular;
    uniform float u_AlphaTestValue;
    uniform float u_Shininess;
};

gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) and gl.getActiveUniform(program, i) still contaion uniformBuffer item( for example u_DiffuseColor,it's redundant!), the only one thing I found is gl.getUniformLocation(program, uniName) will return null.

is there another better way i can get uniforms not include uniformBuffer item,because the i should dispose them with two different way.

How can I find a list of all the uniforms in OpenGL es 2.0 vertex shader pro Maybe this is not best way when have uniformBuffer block in shader with opengles3.0

2 Answers2

2

Given some list of active uniform indices, you can query the value of a property for each item in that list with getActiveUniforms. Among the queryable properties is UNIFORM_BLOCK_INDEX, which is the index of the uniform block the uniform is a member of. If it's not a member of any block, the value will be -1.

So basically, you build a list of all the uniform indices (0 to ACTIVE_UNIFORMS - 1), query their block index, and then query the properties only for the indices whose block index is -1.

Alternatively, you could query, for each active block (0 to ACTIVE_UNIFORM_BLOCKS - 1), the list of uniform indices that are a member of that block with getActiveUniformBlockParameter, passing UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES as the property to be queried. Any uniform index not in one of these lists is therefore not a member of a block.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
1

You can get all uniforms and which blocks they are in by calling gl.getActiveUniform and gl.getActiveUniforms. gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) returns the number of uniforms. You then create an array of indices to pass to gl.getActiveUniforms and pass it gl.UNIFORM_BLOCK_INDEX. -1 = not in a block.

const vs = `#version 300 es

// NOTE: We need to mark these as mediump to match
// the fragment shader (or of course we could mark
// the fragment shader's uniform block to highp)
//
layout(std140) uniform u_testBlock
{
    mediump vec4 foo;
    mediump vec3 bar;
};

void main() {
  gl_Position = foo;
}
`;
const fs = `#version 300 es
precision mediump float;

layout(std140) uniform u_testBlock
{
    vec4 foo;
    vec3 bar;
};

uniform vec2 blat;

out vec4 theColor;

void main() {
  theColor = vec4(bar + vec3(blat, 0), 1);
}
`;

function main() {
  const gl = document.createElement("canvas").getContext("webgl2");
  if (!gl) {
    return alert("ERROR: need WebGL 2 support");
  }
  const program = twgl.createProgram(gl, [vs, fs]);


  const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
  const indices = [...Array(numUniforms).keys()];
  const blockIndices = gl.getActiveUniforms(program, indices, gl.UNIFORM_BLOCK_INDEX);
    const offsets = gl.getActiveUniforms(program, indices, gl.UNIFORM_OFFSET);

  for (let ii = 0; ii < numUniforms; ++ii) {
    const uniformInfo = gl.getActiveUniform(program, ii);
    if (isBuiltIn(uniformInfo)) {
        continue;
    }
    const {name, type, size} = uniformInfo;
    const blockIndex = blockIndices[ii];
    const offset = offsets[ii];
    console.log(
       name, size, glEnumToString(gl, type),
       blockIndex, offset);
  }
}

function isBuiltIn(info) {
  const name = info.name;
  return name.startsWith("gl_") || name.startsWith("webgl_");
}

function glEnumToString(gl, value) {
  const keys = [];
  for (const key in gl) {
    if (gl[key] === value) {
      keys.push(key);
    }
  }
  return keys.length ? keys.join(' | ') : `0x${value.toString(16)}`;
}

main();
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>

Other questions related to using uniform blocks

What is the correct sequence for uploading a uniform block?

Updating Uniform Buffer Data in WebGL 2?

Bind multiple Uniform Buffer Objects

gman
  • 100,619
  • 31
  • 269
  • 393