2

当我像这样在着色器中编写 uniformBuffer 时。

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) 和 gl.getActiveUniform(program, i) 仍然包含 uniformBuffer 项(例如 u_DiffuseColor,它是多余的!),我发现的唯一一件事是 gl.getUniformLocation(program, uniName) 将返回无效的。

是否有另一种更好的方法可以获得不包括 uniformBuffer 项目的制服,因为我应该用两种不同的方式处理它们。

如何在 OpenGL es 2.0 vertex shader pro 中找到所有制服 列表

4

2 回答 2

2

给定一些活动统一索引列表,您可以使用 查询该列表中每个项目的属性值getActiveUniforms。在可查询的属性中有UNIFORM_BLOCK_INDEX,它是统一块的索引,统一块是其成员。如果它不是任何块的成员,则该值为-1。

因此,基本上,您构建所有统一索引(0 到ACTIVE_UNIFORMS- 1)的列表,查询它们的块索引,然后仅查询块索引为 -1 的索引的属性。

或者,您可以为每个活动块(0 到ACTIVE_UNIFORM_BLOCKS- 1)查询作为该块成员的统一索引列表,并作为要查询的属性getActiveUniformBlockParameter传递。UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES因此,不在这些列表之一中的任何统一索引都不是块的成员。

于 2020-03-30T15:35:46.730 回答
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

于 2020-03-31T02:41:34.570 回答