cocos变灰图

来源:互联网 发布:淘宝考试题和答案2016 编辑:程序博客网 时间:2024/05/16 05:53

转载出处:http://blog.csdn.net/u010223072/article/details/49640147


本人使用cocos2dx-3.3


前言:游戏中有很多按钮控件,它们一般会有选中和未选中2种状态。我们如果要区分这两种状态的表现,很多时候是直接叫美术给两种状态下的资源,或直接setColor设置颜色。这样无疑增加了资源的大小或不美观(看需求)。本节将介绍怎么通过opengl es程序来实现图片置灰操作。

注:这个置灰操作是基于Cocos-Lua的,具体原理分析这里不打算介绍,主要讲如何实现。

实现步骤

  • Lua端操作:

1,置灰Lua代码(ShaderEffect.lua)

local ShaderEffect = {        vertDefaultSource = "\n"..        "attribute vec4 a_position; \n" ..        "attribute vec2 a_texCoord; \n" ..        "attribute vec4 a_color; \n"..                                                            "#ifdef GL_ES  \n"..        "varying lowp vec4 v_fragmentColor;\n"..        "varying mediump vec2 v_texCoord;\n"..        "#else                      \n" ..        "varying vec4 v_fragmentColor; \n" ..        "varying vec2 v_texCoord;  \n"..        "#endif    \n"..        "void main() \n"..        "{\n" ..        "gl_Position = CC_PMatrix * a_position; \n"..        "v_fragmentColor = a_color;\n"..        "v_texCoord = a_texCoord;\n"..        "}",        pszFragSource2 = "#ifdef GL_ES \n" ..        "precision mediump float; \n" ..        "#endif \n" ..        "uniform sampler2D u_texture; \n" ..        "varying vec2 v_texCoord; \n" ..        "varying vec4 v_fragmentColor;\n"..        "uniform vec2 pix_size;\n"..        "void main(void) \n" ..        "{ \n" ..        "vec4 sum = vec4(0, 0, 0, 0); \n" ..        "sum += texture2D(u_texture, v_texCoord - 4.0 * pix_size) * 0.05;\n"..        "sum += texture2D(u_texture, v_texCoord - 3.0 * pix_size) * 0.09;\n"..        "sum += texture2D(u_texture, v_texCoord - 2.0 * pix_size) * 0.12;\n"..        "sum += texture2D(u_texture, v_texCoord - 1.0 * pix_size) * 0.15;\n"..        "sum += texture2D(u_texture, v_texCoord                 ) * 0.16;\n"..        "sum += texture2D(u_texture, v_texCoord + 1.0 * pix_size) * 0.15;\n"..        "sum += texture2D(u_texture, v_texCoord + 2.0 * pix_size) * 0.12;\n"..        "sum += texture2D(u_texture, v_texCoord + 3.0 * pix_size) * 0.09;\n"..        "sum += texture2D(u_texture, v_texCoord + 4.0 * pix_size) * 0.05;\n"..        "gl_FragColor = sum;\n"..        "}",        --变灰        psGrayShader = "#ifdef GL_ES \n" ..        "precision mediump float; \n" ..        "#endif \n" ..        "varying vec4 v_fragmentColor; \n" ..        "varying vec2 v_texCoord; \n" ..        "void main(void) \n" ..        "{ \n" ..        "vec4 c = texture2D(CC_Texture0, v_texCoord); \n" ..        "gl_FragColor.xyz = vec3(0.3*c.r + 0.15*c.g +0.11*c.b); \n"..        "gl_FragColor.w = c.w; \n"..        "}" ,        --移除变灰        psRemoveGrayShader = "#ifdef GL_ES \n" ..        "precision mediump float; \n" ..        "#endif \n" ..        "varying vec4 v_fragmentColor; \n" ..        "varying vec2 v_texCoord; \n" ..        "void main(void) \n" ..        "{ \n" ..        "gl_FragColor = texture2D(CC_Texture0, v_texCoord); \n" ..        "}" ,        pszFragSource1 = "#ifdef GL_ES \n" ..        "precision mediump float; \n" ..        "#endif \n" ..        "varying vec4 v_fragmentColor; \n" ..        "varying vec2 v_texCoord; \n" ..        "void main(void) \n" ..        "{ \n" ..        "vec4 c = texture2D(CC_Texture0, v_texCoord); \n" ..        "gl_FragColor.xyz = vec3(0.3*c.r + 0.15*c.g +0.11*c.b); \n"..        "gl_FragColor.w = c.w; \n"..        "}" ,}function ShaderEffect:init()    local pGrayProgram = cc.GLProgram:createWithByteArrays(self.vertDefaultSource,self.psGrayShader)    pGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION,cc.VERTEX_ATTRIB_POSITION)    pGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_COLOR,cc.VERTEX_ATTRIB_COLOR)    pGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD,cc.VERTEX_ATTRIB_FLAG_TEX_COORDS)    pGrayProgram:link()    pGrayProgram:use()    pGrayProgram:updateUniforms()    cc.GLProgramCache:getInstance():addGLProgram(pGrayProgram,"pGrayProgram")    local pRemoveGrayProgram = cc.GLProgram:createWithByteArrays(self.vertDefaultSource,self.psRemoveGrayShader)    pRemoveGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION,cc.VERTEX_ATTRIB_POSITION)    pRemoveGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_COLOR,cc.VERTEX_ATTRIB_COLOR)    pRemoveGrayProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD,cc.VERTEX_ATTRIB_FLAG_TEX_COORDS)    pRemoveGrayProgram:link()    pRemoveGrayProgram:use()    pRemoveGrayProgram:updateUniforms()    cc.GLProgramCache:getInstance():addGLProgram(pRemoveGrayProgram,"pRemoveGrayProgram")endfunction ShaderEffect:addGrayNode(node)    --变灰的    local pProgram = cc.GLProgram:createWithByteArrays(self.vertDefaultSource,self.psGrayShader)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION,cc.VERTEX_ATTRIB_POSITION)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_COLOR,cc.VERTEX_ATTRIB_COLOR)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD,cc.VERTEX_ATTRIB_FLAG_TEX_COORDS)    pProgram:link()    pProgram:use()    pProgram:updateUniforms()    node:setGLProgram(pProgram)endfunction ShaderEffect:removeGrayNode(node)    local pProgram = cc.GLProgram:createWithByteArrays(self.vertDefaultSource,self.psRemoveGrayShader)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION,cc.VERTEX_ATTRIB_POSITION)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_COLOR,cc.VERTEX_ATTRIB_COLOR)    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD,cc.VERTEX_ATTRIB_FLAG_TEX_COORDS)    pProgram:link()    pProgram:use()    pProgram:updateUniforms()    node:setGLProgram(pProgram)endfunction ShaderEffect:AddBlur(node)    local fileUtiles = cc.FileUtils:getInstance()    local vertSource = self.vertDefaultSource    local fragSource = fileUtiles:getStringFromFile("shaders/example_Blur.fsh")    local pProgram = cc.GLProgram:createWithByteArrays(vertSource, fragSource)    node:setGLProgram(pProgram)    --local glprogramstate = cc.GLProgramState:getOrCreateWithGLProgram(pProgram)    local size = node:getTexture():getContentSizeInPixels()    node:getGLProgramState():setUniformVec2("pix_size", size)    node:getGLProgramState():setUniformFloat("blurRadius", 20.0);    node:getGLProgramState():setUniformFloat("sampleNum", 0.1);--    --    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION,cc.VERTEX_ATTRIB_POSITION)--    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_COLOR,cc.VERTEX_ATTRIB_COLOR)--    pProgram:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD,cc.VERTEX_ATTRIB_FLAG_TEX_COORDS)    pProgram:link()    pProgram:use()    pProgram:updateUniforms()end-- 按钮置灰function ShaderEffect:addGrayButton(button)    if button == nil then        cclog("param can't be nil")        return    end    -- 遍历按钮的子节点    --[[local children = button:getChildren()    if children and #children>0 then        for _, aSprite in ipairs(children) do            if aSprite.getVirtualRenderer then                self:addGrayNode(aSprite:getVirtualRenderer():getSprite())                    elseif aSprite.setGLProgram then                self:addGrayNode(aSprite)            end        end    end    ]]    -- 按钮本身    local sprite9 = button:getVirtualRenderer()         local sprite = sprite9:getSprite()    self:addGrayNode(sprite)end-- 按钮返回正常function ShaderEffect:removeGrayButton(button)    if button == nil then        cclog("param can't be nil")        return    end    -- 按钮本身    local sprite9 = button:getVirtualRenderer()       local sprite = sprite9:getSprite()    self:removeGrayNode(sprite)end--遍历变灰function ShaderEffect:setGrayAndChild(node,isNotRecursive)    if node == nil then        return    end    local array = node:getSpriteChildren()    for key, var in pairs(array) do        var:setGLProgram(cc.GLProgramCache:getInstance():getGLProgram("pGrayProgram"))    end    if isNotRecursive ~= true then        --children        local array = node:getChildren()        for key, var in pairs(array) do            self:setGrayAndChild(var)        end    endend--遍历取消变灰function ShaderEffect:setRemoveGrayAndChild(node,isNotRecursive)    if node == nil then        return    end    local array = node:getSpriteChildren()    for key, var in pairs(array) do        var:setGLProgram(cc.GLProgramCache:getInstance():getGLProgram("pRemoveGrayProgram"))    end    if isNotRecursive ~= true then        --children        local array = node:getChildren()        for key, var in pairs(array) do            self:setRemoveGrayAndChild(var)        end    endendShaderEffect:init()return ShaderEffect

使用

local ShaderEffect = require("ShaderEffect")  --加载ShaderEffect:setGrayAndChild(Button)  --置灰ShaderEffect:setRemoveGrayAndChild(Button)  --取消置灰

2c++

Lua端代码需要调用C++端扩展的getSpriteChildren()接口(得到控件的精灵对象),下面就来看看C++端怎么来扩展这个接口(这里以Button置灰为例,其它控件思路一样):

1,首先在基类CCNode.h中添加这个接口,保证其它控件(没有实现的)至少不会运行出错。

virtual Vector<Node*> getSpriteChildren() { Vector<Node*> vec; return vec; } //@cxx

2,既然以按钮控件为例,就先找到UIButton.h中表示按钮精灵信息的成员,发现是这4个变量表示:
Scale9Sprite* _buttonNormalRenderer; //初始状态图片 Scale9Sprite* _buttonClickedRenderer; //点击状态图片 Scale9Sprite* _buttonDisableRenderer;//抬起后图片 Label* _titleRenderer; //按钮里文字
从这里可以看出,要得到按钮的所有精灵,还得去Scal9Sprite类和Label类中修改,先上UIButton类中getSpriteChildren()的实现:

Vector<Node*> Button::getSpriteChildren(){    Vector<Node*> vec;    if (_buttonNormalRenderer) {        vec.pushBack(_buttonNormalRenderer->getSpriteChildren());    }    if (_buttonClickedRenderer) {        vec.pushBack(_buttonClickedRenderer->getSpriteChildren());    }    if (_buttonDisableRenderer) {        vec.pushBack(_buttonDisableRenderer->getSpriteChildren());    }    if (_titleRenderer) {        vec.pushBack(_titleRenderer->getSpriteChildren());    }    return vec;}

3,上面按钮图片资源数据既然是返回的Scale9Sprite对象的指针,那我们就得去这个类中得到精灵信息,具体getSpriteChildren()的实现如下:
Vector<Node*> Scale9Sprite::getSpriteChildren()    {        Vector<Node*> vec;        if (_scale9Image) {            vec.pushBack(_scale9Image);        }        if (_topLeftSprite) {            vec.pushBack(_topLeftSprite);        }        if (_topSprite) {            vec.pushBack(_topSprite);        }        if (_topRightSprite) {            vec.pushBack(_topRightSprite);        }        if (_leftSprite) {            vec.pushBack(_leftSprite);        }        if (_centerSprite) {            vec.pushBack(_centerSprite);        }        if (_rightSprite) {            vec.pushBack(_rightSprite);        }        if (_bottomLeftSprite) {            vec.pushBack(_bottomLeftSprite);        }        if (_bottomSprite) {            vec.pushBack(_bottomSprite);        }        if (_bottomRightSprite) {            vec.pushBack(_bottomRightSprite);        }        return vec;    }

4,按钮的文字数据返回的是Label对象指针,同样,我们得去Label类中实现getSpriteChildren()得到文字的精灵,代码如下:

Vector<Node*> Label::getSpriteChildren(){    Vector<Node*> vec;    if (_textSprite) {        vec.pushBack(_textSprite);    }    return vec;}

5,好,这样按钮的4个相关精灵数据都能得到了,接下来就是tolua绑定到Lua端调用,如何绑定,前面章节有介绍。(Lua Shader那边反正是要最终得到 Sprite* 精灵对象来进行处理,遇到间接的纹理对象就一层一层的剥吧…)



0 0
原创粉丝点击