如何在WebGL中获取程序的所有属性绑定?

时间:2013-06-11 23:43:52

标签: webgl

我有一个WebGL应用程序,其中一些属性通过getAttribLocation绑定到程序,一些属性通过bindAttribLocation绑定到程序。

有没有办法可以将所有字符串名称映射到程序的索引/值?另外,我可以在这一点上做到这一点?我认为在链接程序后可以调用getAttribLocation,对吗?

2 个答案:

答案 0 :(得分:3)

是的,你可以这样做。这是我的Cubes代码的摘录,它们绑定了一些属性并查找其他属性的索引:

for (var attribName in boundAttribLocations) {
  var index = boundAttribLocations[attribName];
  if (typeof index === "number") {
    gl.bindAttribLocation(program, index, attribName);
  } else {
    if (typeof console !== "undefined") {
      console.warn("Enumerable non-number", attribName, "in boundAttribLocations object", boundAttribLocations);
    }
  }
}

gl.linkProgram(program);

if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  throw new Error(gl.getProgramInfoLog(program));
}

var i, name;
var attribs = Object.create(boundAttribLocations);
for (i = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) - 1; i >= 0; i--) {
  name = gl.getActiveAttrib(program, i).name;
  attribs[name] = gl.getAttribLocation(program, name);
}

如果我没记错的话,boundAttribLocationsObject.create)的继承是attribs将包含所有绑定属性的有效位置,包括当前着色器未使用的属性, GL不会使用getActiveAttrib进行枚举。

答案 1 :(得分:1)

您可以查询所有这些属性

假设program是与gl.linkProgram成功关联的着色器程序,那么

const numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (let ii = 0; ii < numAttribs; ++ii) {
  const attribInfo = gl.getActiveAttrib(program, ii);
  const index = gl.getAttribLocation(program, attribInfo.name);
  console.log(index, attribInfo.name);
}

示例:

const gl = document.createElement("canvas").getContext("webgl");

const vs = `
attribute vec4 position;
attribute vec3 normal;
attribute vec4 color;
attribute vec2 texcoord;
attribute float extra;
void main() {
  // it's only important we use all the attributes so they don't get optimized
  // out. It's not important that this shader makes no sense since that's
  // not the point of this example.
  gl_Position = position + vec4(normal, 0) + color + vec4(texcoord, extra, 0); 
}
`;
const fs = `
precision mediump float;
void main() {
  gl_FragColor = vec4(1);
}
`;

const prg = createProgram(gl, vs, fs);
showAttributes(gl, prg);

function showAttributes(gl, program) {
  const numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
  for (let ii = 0; ii < numAttribs; ++ii) {
    const attribInfo = gl.getActiveAttrib(program, ii);
    const index = gl.getAttribLocation(program, attribInfo.name);
    log("index:", index, "size:", attribInfo.size, "type:", glEnumToString(gl, attribInfo.type).padEnd(10), "name:", attribInfo.name);
  }
}

function createProgram(gl, vSrc, fSrc) {
  const vs = createShader(gl, gl.VERTEX_SHADER, vSrc);
  const fs = createShader(gl, gl.FRAGMENT_SHADER, fSrc);
  const p = gl.createProgram();
  gl.attachShader(p, vs);
  gl.attachShader(p, fs);
  gl.linkProgram(p);
  return p;
}

function createShader(gl, type, src) {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  return s;
}

function glEnumToString(gl, value) {
  for (let key in gl) {
    if (gl[key] === value) {
      return key;
    }
  }
  return "0x" + value.toString(16);
}

function log(...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(' ');
  document.body.appendChild(elem);
}
pre { margin: 0; }