webgl2.0, как я могу получить все формы, кроме элементаiformBuffer - PullRequest
2 голосов
/ 30 марта 2020

, когда я пишуiformBuffer в шейдер, как это избыточно!), единственное, что я обнаружил, это gl.getUniformLocation (program, uniName), который вернет значение null.

есть еще один лучший способ получить униформу, не включающую элементiformBuffer, потому что я должен располагать их с помощью два разных способа.

Как найти список всех униформ в вершинном шейдере OpenGL es 2.0 pro Может быть, это не лучший способ, когда в шейдере есть блокiformBuffer с opengles3.0

Ответы [ 2 ]

2 голосов
/ 30 марта 2020

Учитывая некоторый список активных единообразных индексов, вы можете запросить значение свойства для каждого элемента в этом списке с помощью getActiveUniforms. Среди запрашиваемых свойств - UNIFORM_BLOCK_INDEX, который является индексом унифицированного блока, членом которого является униформа. Если он не является членом какого-либо блока, значение будет равно -1.

Таким образом, в основном вы строите список всех унифицированных индексов (от 0 до ACTIVE_UNIFORMS - 1), запрашивает их индекс блока и затем запросите свойства только для индексов, чей индекс блока равен -1.

В качестве альтернативы, вы можете запросить для каждого активного блока (от 0 до ACTIVE_UNIFORM_BLOCKS - 1) список унифицированных индексов, которые являются членами этого блока с getActiveUniformBlockParameter, передавая UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES в качестве запрашиваемого свойства. Следовательно, любой унифицированный индекс не в одном из этих списков не является членом блока.

1 голос
/ 31 марта 2020

Вы можете получить все формы и блоки, в которых они находятся, позвонив gl.getActiveUniform и gl.getActiveUniforms. gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) возвращает количество униформ. Затем вы создаете массив индексов для передачи в gl.getActiveUniforms и передачи его gl.UNIFORM_BLOCK_INDEX. -1 = не в блоке.

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>

Другие вопросы, связанные с использованием единообразных блоков

Какая правильная последовательность для загрузки единообразного блока?

Обновление данных унифицированного буфера в WebGL 2?

Связывание нескольких объектов унифицированного буфера

...