我目前正在编写一个自动生成统一设置器的函数,因此我需要统一变量类型的信息。现在的想法是使用通过调用gl.getActiveUniform
返回的对象中存储的数据类型,这种方法期望统一的索引作为第二个参数,因此必须对其进行评估第一
但据我所知,没有办法通过传入变量的标识符从WebGL接口检索统一的索引,这是对的吗?
原因是gl.getUniformLocation
,但此方法返回的对象没有任何公共成员,它的唯一目的似乎是作为setter函数的参数传入 - 尽管它是一个提供制服指数信息的合适地方,不是吗?
最后有gl.getProgramParameter
,可以用gl.ACTIVE_UNIFORMS
作为第二个参数调用,但它只返回着色器中声明的制服计数。
所以,问题是,我是否必须自己提供有关变量索引值的信息,或者WebGL中是否有内置功能来完成这项工作?
修改
好吧,有时你看不到树木的森林。显而易见的解决方案是不从变量名中获取索引值,而是从索引获取变量名,因为统一的名称也是gl.getActiveUniform
返回的对象的成员。
该过程将首先使用gl.getProgramParameter
调用gl.ACTIVE_UNIFORMS
以获取变量计数,然后循环遍历此项,在每次迭代时调用gl.getActiveUniform
。不过,我认为这将是更优雅的解决方案。
但是,如果有直接的方法可以通过它的名字来获得单一制服的索引,那么知道它会很有趣......
答案 0 :(得分:1)
您在编辑中提出的建议基本上就是我一直以来的做法。像这样:
function makeUniformSetters(program){
var unifInfos = {};
var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i = 0; i < uniformCount; i++) {
var info = gl.getActiveUniform(program, i);
info.loc = gl.getUniformLocation(program, info.name);
unifInfos[info.name] = info;
}
var unifSetters = {};
Object.keys(unifInfos).forEach(function(k){
unifSetters[k] = createUniformSetter(k);
});
function createUniformSetter(n){
var info = unifInfos[n];
if (info === undefined){
console.log("program is not using uniform "+n);
return function noOp(){};
}
var u = info;
var loc = u.loc;
var type = u.type;
if (type === gl.FLOAT)
return function(v){ gl.uniform1f(loc,v);};
if (type === gl.FLOAT_VEC2)
return function(v){ gl.uniform2fv(loc,v);};
// etc
}
return unifSetters;
}
然后您可以这样使用它:unifSetters["u_viewProjection"](mat4);
我修改了代码以摆脱引擎特定的部分,因此它可能无法100%开箱即用。但希望这个想法应该清楚。