我有一个WebGL应用程序,其中一些属性通过getAttribLocation绑定到程序,一些属性通过bindAttribLocation绑定到程序。
有没有办法可以将所有字符串名称映射到程序的索引/值?另外,我可以在这一点上做到这一点?我认为在链接程序后可以调用getAttribLocation,对吗?
答案 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);
}
如果我没记错的话,boundAttribLocations
(Object.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; }