2

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

有没有一种方法可以将所有字符串名称映射到程序的属性索引/值?另外,在什么时候我可以这样做?我认为 getAttribLocation 可以在程序链接后调用,对吗?

4

2 回答 2

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);
}

如果我没记错的话,boundAttribLocations( Object.create)的继承attribs将包含所有绑定属性的有效位置,包括当前着色器未使用的那些,GL 不会用getActiveAttrib.

于 2013-06-13T05:30:39.060 回答
3

您可以像这样查询所有属性

假设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; }

于 2017-07-11T17:26:16.627 回答