如何获得统一变量的索引?

时间:2016-01-18 08:06:02

标签: webgl

我目前正在编写一个自动生成统一设置器的函数,因此我需要统一变量类型的信息。现在的想法是使用通过调用gl.getActiveUniform返回的对象中存储的数据类型,这种方法期望统一的索引作为第二个参数,因此必须对其进行评估第一

但据我所知,没有办法通过传入变量的标识符从WebGL接口检索统一的索引,这是对的吗?

原因是gl.getUniformLocation,但此方法返回的对象没有任何公共成员,它的唯一目的似乎是作为setter函数的参数传入 - 尽管它是一个提供制服指数信息的合适地方,不是吗?

最后有gl.getProgramParameter,可以用gl.ACTIVE_UNIFORMS作为第二个参数调用,但它只返回着色器中声明的制服计数。

所以,问题是,我是否必须自己提供有关变量索引值的信息,或者WebGL中是否有内置功能来完成这项工作?

修改

好吧,有时你看不到树木的森林。显而易见的解决方案是不从变量名中获取索引值,而是从索引获取变量名,因为统一的名称也是gl.getActiveUniform返回的对象的成员。

该过程将首先使用gl.getProgramParameter调用gl.ACTIVE_UNIFORMS以获取变量计数,然后循环遍历此项,在每次迭代时调用gl.getActiveUniform。不过,我认为这将是更优雅的解决方案。

但是,如果有直接的方法可以通过它的名字来获得单一制服的索引,那么知道它会很有趣......

1 个答案:

答案 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%开箱即用。但希望这个想法应该清楚。