Cocos2dx-- 图片置灰实现

Cocos2dx-- 图片置灰实现,第1张

概述前言:游戏中有很多按钮控件,它们一般会有选中和未选中2种状态。我们如果要区分这两种状态的表现,很多时候是直接叫美术给两种状态下的资源,或直接setColor设置颜色。这样无疑增加了资源的大小或不美观(看需求)。本节将介绍怎么通过opengl es程序来实现图片置灰 *** 作。 注:这个置灰 *** 作是基于Cocos-Lua的,具体原理分析这里不打算介绍,主要讲如何实现。 实现步骤 Lua端 *** 作: 1,置灰Lu

前言:游戏中有很多按钮控件,它们一般会有选中和未选中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); \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,}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_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,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

2,使用

local ShaderEffect = require("ShaderEffect")  --加载ShaderEffect:setGrayAndChild(button)  --置灰ShaderEffect:setRemoveGrayAndChild(button)  --取消置灰
cocos C++端 *** 作:

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* 精灵对象来进行处理,遇到间接的纹理对象就一层一层的剥吧…)

效果图 总结

以上是内存溢出为你收集整理的Cocos2dx-- 图片置灰实现全部内容,希望文章能够帮你解决Cocos2dx-- 图片置灰实现所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1073963.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存