请教一下Shader怎么传数组

比如说,一个光束的shader,我需要从这边传入一个坐标数组来生成多道光束,试了一天没找到该怎么做,而setUniformVec2v以及setUniformFloatv试了也不行

API没用错,大概是因为你传的是临时变量导致shader调用时数组已经不存在了?

谢谢你的回复,不过我把临时变量改为脚本属性似乎也不行
this.v=[1] var glProgram_state = cc.GLProgramState.getOrCreateWithGLProgram(glProgram); glProgram_state.setUniformFloatv("arr", 1,this.v);
shader那边是
uniform float arr[1]; void main( void ) { gl_FragColor=vec4(arr[0],0,0,1); }
画面是黑色的
之前忘记说了,使用setUniformFloatv时报错wrong number of arguments

或者,我在网上也有看到说用texture传的,请教一下用texture又该怎么传

这个问题没有办法解决的吗

原生平台传入数组应该是

setUniformVec2

我代码里的一段:

this._glProgram_state.setUniformVec2(this._iResolutiion, cc.p(this.node.getContentSize().width, this.node.getContentSize().height));//0.5

片段着色器这边应该这样接收

uniform vec2 iResolution;

ps:原生平台和web的接口方法是不同的

谢谢你的回复,不过这个只是传二维向量的函数吧

哦, 看了下api传输组的确是

setUniformFloatv

但是是js帮顶这一块,好像原生不支持
在这一段:

static bool js_cocos2dx_GLProgramState_setUniformFloatv(se::State& s)
{
    CC_UNUSED bool ok = true;
    cocos2d::GLProgramState* cobj = (cocos2d::GLProgramState*)s.nativeThisObject();
    SE_PRECONDITION2( cobj, false, "js_cocos2dx_GLProgramState_setUniformFloatv : Invalid Native Object");
    const auto& args = s.args();
    size_t argc = args.size();
    do {
        if (argc == 3) {
            int arg0 = 0;
            ok &= seval_to_int32(args[0], (int32_t*)&arg0);
            if (!ok) { ok = true; break; }
            ssize_t arg1 = 0;
            ok &= seval_to_ssize(args[1], &arg1);
            if (!ok) { ok = true; break; }
            const float* arg2 = 0;
            #pragma warning NO CONVERSION TO NATIVE FOR float* //这一段有说明
            ok = false;//这里肯定break出去了
            if (!ok) { ok = true; break; }
            cobj->setUniformFloatv(arg0, arg1, arg2);
            return true;
        }
    } while(false);

    do {
        if (argc == 3) {
            std::string arg0;
            ok &= seval_to_std_string(args[0], &arg0);
            if (!ok) { ok = true; break; }
            ssize_t arg1 = 0;
            ok &= seval_to_ssize(args[1], &arg1);
            if (!ok) { ok = true; break; }
            const float* arg2 = 0;
            #pragma warning NO CONVERSION TO NATIVE FOR float*
            ok = false;
            if (!ok) { ok = true; break; }//这一段也是直接break了
            cobj->setUniformFloatv(arg0, arg1, arg2);
            return true;
        }
    } while(false);

    SE_REPORT_ERROR("wrong number of arguments: %d", (int)argc);//必然会走这一句
    return false;
}

所以这个现在肯定是有问题的,看 @dumganhar 能不能帮忙看看.

1赞

这块可能需要手动绑定了。
已经建立了issue,你可以自己先绑定试试看。不行的话,就等官方支持吧。

悲剧了,实现不了。

setUniformXXXv接口传入的是size和pointer,看GLProgramState的内部实现:

void GLProgramState::setUniformVec2v(const std::string& uniformName, ssize_t size, const Vec2* pointer)
{
    auto v = getUniformValue(uniformName);
    if (v)
        v->setVec2v(size, pointer);
    else
        CCLOG("cocos2d: warning: Uniform not found: %s", uniformName.c_str());
}

void UniformValue::setVec2v(ssize_t size, const Vec2* pointer)
{
    CCASSERT(_uniform->type == GL_FLOAT_VEC2, "Wrong type: expecting GL_FLOAT_VEC2");
    _value.v2f.pointer = (const float*)pointer; // 我雷了个去,这里直接是指针赋值
    _value.v2f.size = (GLsizei)size;
    _type = Type::POINTER;
}

搜索整个-x源码,原来之前只有CCMesh中用到,-lite是没有用到的。

看到没,这些调用其实都是传入类成员变量,他们的生命周期是依附在对应的CCMesh实例上的。所以内部使用setUniformXXXv并不会导致问题。

但是指针直接赋值在JSB中有个问题:

绑定层只能new一个vector出来,但是却不知道何时去释放这个vector。好鸡肋。

static bool js_cocos2dx_GLProgramState_setUniformVec2v(se::State& s)
{
    CC_UNUSED bool ok = true;
    cocos2d::GLProgramState* cobj = (cocos2d::GLProgramState*)s.nativeThisObject();
    SE_PRECONDITION2( cobj, false, "js_cocos2dx_GLProgramState_setUniformVec2v : Invalid Native Object");
    const auto& args = s.args();
    size_t argc = args.size();
    do {
        if (argc == 2) {
            int arg0 = 0;
            ok &= seval_to_int32(args[0], (int32_t*)&arg0);
            if (!ok) { ok = true; break; }
            std::vector<cocos2d::Vec2>* uniformValues = new std::vector<cocos2d::Vec2>; // 不知道什么时候去释放了,导致内存泄露啦。。。。
            ok &= seval_to_std_vector_Vec2(args[1], uniformValues);
            if (!ok) { ok = true; break; }
            cobj->setUniformVec2v(arg0, uniformValues.size(), uniformValues.data());
            return true;
        }
    } while(false);

所以这个接口的绑定在JSB上是有问题的,目前暂时无法在不修改-x源码的情况下做到。

了解了:2:

问下,这个issue 在creator的下个版本可以解决吗,

web模式都没什么问题

看了源码 setUniformVec4也没有导出jsb接口 。 这个比较急需,我目前要传20个float变量,没有v干不了,希望能重视一下,麻烦了。

希望尽快把setUniformXXXv补充上,谢谢

如果只是api 调用麻烦的话,感觉可以在js这边封装一个函数,传入一个map解决。

如果是效率问题的话就只能改c++了

map? 我目前做法是传入2个mat4变量,这样就可以使用最多32个float变量, :joy:

我想的是你如果在 shader 中定义多个 unitform 的话:

fuction batchSetUniform(unitformMapping) {
    (for key in unitformMapping) {
         shader.setUniformLocationWithXXX(key, unitformMapping[key]);
    }
}

这样调用的时候只用:

batchSetUniform({
    a: 1,
    b: 2,
})

不知道这样可行不? 具体调用 setUniformLocationWithXXX 什么可以用 if 语句控制一下.