我制作了具有4种不同雨滴纹理的雨景,每个雨滴精灵在创建并添加到屏幕时随机选择雨滴纹理。所有雨滴精灵共享一个相同的着色器。
问题是,当我在屏幕上添加一个新的雨滴时,所有添加到场景中的前雨滴都会改变其纹理,使其与新的雨滴相同。
我的代码如下:
local function addOneRainDrop()
local rainStyleNumber = math.random(1,4)
local rainDrop = cc.Sprite:create("rainDrop"..tostring(rainStyleNumber)..".png")
rainShader:use()
rainShader:updateUniforms()
rainShader:setUniformsForBuiltins()
gl.activeTexture(GL_TEXTURE1) -- here may be the reason
gl.bindTexture(GL_TEXTURE_2D, rainDrop:getTexture():getName())
gl.activeTexture(GL_TEXTURE2)
gl.bindTexture(GL_TEXTURE_2D, rainNormal[rainStyleNumber]:getName())
gl.activeTexture(GL_TEXTURE0)
rainDrop:setGLProgram(rainShader)
rainDropLayer:addChild(rainDrop)
end
在我的着色器中,我只是采样CC_Texture0,CC_Texture1,CC_Texture2和输出颜色。我认为这不是着色器的问题。我不知道Cocos2d如何管理它的着色器状态和不同精灵的制服,可能直接从CCSprite继承,覆盖"绘制"并通过我自己管理纹理可以解决问题,但它有点复杂。
有更好的想法吗?
=============================================== ==============================
更新:
我发现我可以使用GLProgramState为每个精灵存储制服。引自cocos2d的网站
GLProgram可以被数千个节点使用,但是如果要使用不同的统一值,那么每个节点都需要自己的GLProgramState
所以我将代码更改为以下内容:
local function addOneRainDrop()
local rainStyleNumber = math.random(1,4)
local rainDrop = cc.Sprite:create("rainDrop"..tostring(rainStyleNumber)..".png")
local glprogramstate = cc.GLProgramState:getOrCreateWithGLProgram(rainShader);
glprogramstate:setUniformTexture("rainDrop", rainDrop:getTexture():getName());
glprogramstate:setUniformTexture("textureBackground", bg:getTexture():getName());
glprogramstate:setUniformTexture("rainDropNormals", rainNormal[rainStyleNumber]:getName());
rainDrop:setGLProgramState(glprogramstate);
rainDropLayer:addChild(rainDrop)
end
不幸的是,所有的精灵仍然使用相同的纹理。这与batchedNode有关吗?
答案 0 :(得分:0)
您的问题在于使用 getOrCreateWithGLProgram(),它总是返回相同的 GLProgramState ,因为它使用 rainShader 作为密钥进行缓存。 / p>
我所做的是:
static GLProgram* getOrCreateShader(std::string name, const GLchar* vert, const GLchar* frag)
{
auto cache = GLProgramCache::getInstance();
auto prog = cache->getGLProgram(name);
if(prog == nullptr)
{
prog = GLProgram::createWithByteArrays(vert, frag);
cache->addGLProgram(prog, name);
}
return prog;
}
我的方法从GLchar缓冲区创建一个程序,但您可以创建一个使用磁盘文件的新程序。
auto program = getOrCreateShader("rainShaderName", vertexProgram, fragmentProgram);
auto programState = GLProgramState::create(program);
Sprite* sprite = Sprite::create("yourSpriteImage.png");
programState->setUniformTxeture("u_texture", sprite->getTexture());
sprite->setGLProgramState(programState);
这样,着色器程序只会创建一次,每个精灵都有一个唯一的GLProgramState。