【发布时间】:2014-09-09 11:12:54
【问题描述】:
我正在制作具有 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是如何管理不同精灵的shader的状态和制服的,可能直接继承CCSprite,覆盖“draw”,自己管理纹理可以解决问题,但有点复杂。
有更好的想法吗?
================================================ ===============================
更新:
我发现我可以使用 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有关系吗?
【问题讨论】:
-
TEXTURE1和TEXTURE2纹理单元可能会被稍后的另一个 GL 操作覆盖(它们经常使用)。您可能必须在 GL 绘制之前设置TEXTURE1和TEXTURE2单位。我有一个类似的问题。我的解决方案是简单地将纹理单元设置为TEXTURE3和TEXTURE4,因为我不知道 API 的其他部分没有设置这些纹理单元,而且在绘制之前我无法访问 GL 状态。 -
@PeqNP 你是对的,我的解决方案是为不同的雨滴重新创建相同的着色器。幸运的是,我只有 4 种不同的雨滴纹理,这意味着我只需使用不同的纹理创建 4 次相同的着色器,并且所有使用相同纹理的雨滴都可以使用相同的着色器。但是如果每个雨滴都有不同的纹理,我不知道如何处理。
标签: opengl opengl-es lua cocos2d-x shader