比如说,一个光束的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 能不能帮忙看看.
这块可能需要手动绑定了。
已经建立了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源码的情况下做到。
了解了
问下,这个issue 在creator的下个版本可以解决吗,
web模式都没什么问题
看了源码 setUniformVec4也没有导出jsb接口 。 这个比较急需,我目前要传20个float变量,没有v干不了,希望能重视一下,麻烦了。
希望尽快把setUniformXXXv补充上,谢谢
如果只是api 调用麻烦的话,感觉可以在js这边封装一个函数,传入一个map解决。
如果是效率问题的话就只能改c++了
map? 我目前做法是传入2个mat4变量,这样就可以使用最多32个float变量, 
我想的是你如果在 shader 中定义多个 unitform 的话:
fuction batchSetUniform(unitformMapping) {
(for key in unitformMapping) {
shader.setUniformLocationWithXXX(key, unitformMapping[key]);
}
}
这样调用的时候只用:
batchSetUniform({
a: 1,
b: 2,
})
不知道这样可行不? 具体调用 setUniformLocationWithXXX 什么可以用 if 语句控制一下.
