我有一个 WebGL 应用程序,其中一些属性通过 getAttribLocation 绑定到程序,而一些属性通过 bindAttribLocation 绑定到程序。
有没有一种方法可以将所有字符串名称映射到程序的属性索引/值?另外,在什么时候我可以这样做?我认为 getAttribLocation 可以在程序链接后调用,对吗?
我有一个 WebGL 应用程序,其中一些属性通过 getAttribLocation 绑定到程序,而一些属性通过 bindAttribLocation 绑定到程序。
有没有一种方法可以将所有字符串名称映射到程序的属性索引/值?另外,在什么时候我可以这样做?我认为 getAttribLocation 可以在程序链接后调用,对吗?
是的,你可以这样做。这是我的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
.
您可以像这样查询所有属性
假设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; }