在Cocos2d-x v3.x 中实现带颜色滤镜的Sprite

在Cocos2d-x v3.x 中实现带颜色滤镜的Sprite,第1张

概述CocoaChina论坛2014-11-10 16:38:251358 次阅读 一、目的 Cocos2d-x做项目时经常会碰到要对图片进行变色的需求,最常用的就是变灰了,就要让按钮变灰来表示当前的状态是不可点的。 但是Cocos2d-x的Sprite中是没有这个变灰支持的。那么,就要我们自己动手来扩展实现一个。我们让这个带变色功能的Sprite叫做FilterSprite。这个FilterSpri CocoaChina论坛2014-11-10 16:38:251358 次阅读

一、目的

Cocos2d-x做项目时经常会碰到要对图片进行变色的需求,最常用的就是变灰了,就要让按钮变灰来表示当前的状态是不可点的。 但是Cocos2d-x的Sprite中是没有这个变灰支持的。那么,就要我们自己动手来扩展实现一个。我们让这个带变色功能的Sprite叫做FilterSprite。这个FilterSprite扩展了Sprite的功能:可以方便地变换颜色


二、原理

对图片进行颜色变换,就是对图片上的每个像素进行变换。要实现这个,要新创建一个fragmentShader,这个fragmentShader 比sprite的那个fragmentShader多了一个颜色变换矩阵。shader会让图片上每个像素与颜色变换矩阵进行相乘,输出新的像素值。


这个shader是这样的:

@H_419_35@
1 2 3 4 5 6 7 8 9 10 11 12 #ifdefGL_ES precisionmediump float ; #endif uniformsampler2Du_texture; varyingvec2v_texCoord; varyingvec4v_fragmentcolor; uniformmat4fiterMat; voID main( ) { vec4value=v_fragmentcolor*texture2D(u_texture,v_texCoord); gl_Fragcolor=fiterMat*value; };

从shader上我们看到,“filterMat” 就是所谓的颜色变换矩阵,仅仅在原来像素输出前用它处理了一下:与待输出像素相乘。 这个shader是opengl层级的,要应用到coco2dx引擎中,我们要着手实现cocos2dx的FilterSprite类了。


三、实现

实现这个FilterSprite注意几个要点:

引擎中一个shader对应一个GLProgram,所以这个带颜色滤镜的shader(称为filterShader)对应一个GLProgram(称为filterProgram)对象,在实际使用时,是用对GLProgram进行了封装的GLProgramState(称为filterProgramState)对象,FilterSprite对象的_glProgramState要设置成filterProgramState对象,在源码中FilterSprite的initWithTexture进行这个filterShader和filterProgram的关联。

在渲染时要将滤镜传递给shader程序,在源码中就是在onDraw回调时调用:

1
glProgramState->setUniformMat4( "fiterMat" ,m_uSpriteFilter)

四、使用

使用起来非常简单,只需要设置一个颜色矩阵,例如,如果要变灰就设置一个灰度矩阵,如果要恢复原貌就设置一个单位矩阵。

11
Sprite*_sprite1; _sprite1=FilterSprite::create( "Images/background3.png" ); GLfloatfilterMat[16]={ 0.3f,0.3f,0.0f, 0.59f,0.59f, 0.11f,0.11f, 0.0f,1.0f, }; dynamic_cast <FilterSprite*>(_sprite1)->setFilterMat(filterMat);

五、源码

FilterSprite.h:

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @H_554_301@ 41 42 43 44
/**************************************************************************** FilterSpirte.h CreatedbyliaoYanXuanon14-10-21. ****************************************************************************/ #ifndef__FilterSpirte_h #define__FilterSpirte_h #include "cocos2d.h" USING_NS_CC; class FilterSprite: public Sprite{ : FilterSprite(); virtual ~FilterSprite(); static FilterSprite*create(); FilterSprite*create( const std::string&filename); std::string&filename, Rect&rect); FilterSprite*createWithTexture(Texture2D*pTexture); FilterSprite*createWithTexture(Texture2D*pTexture,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">Rect&rect, bool rotated= false ); FilterSprite*createWithSpriteFrame(SpriteFrame*pSpriteFrame); FilterSprite*createWithSpriteFramename( std::string&spriteFramename); initWithTexture(Texture2D*pTexture,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">Rect&tRect); virtual draw(Renderer*renderer,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">Mat4&transform,uint32_tflags)overrIDe; onDraw( setFilterMat(cocos2d::Mat4matrixArray); //to-do提供一个设置滤镜的方法 protected : CustomCommand_customCommand; private : cocos2d::Mat4m_uSpriteFilter; }; #endif


FilterSprite.cpp:

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
/**************************************************************************** ****************************************************************************/ "FilterSprite.h" FilterSprite::FilterSprite( ) { m_uSpriteFilter=Mat4::IDENTITY; } FilterSprite::~FilterSprite() { } FilterSprite*FilterSprite::create() { FilterSprite*sprite= new (std:: nothrow )FilterSprite(); if (sprite&&sprite->init()) { sprite->autorelease(); return sprite; } CC_SAFE_DELETE(sprite); nullptr; } FilterSprite*FilterSprite::create( std::string&filename) { )FilterSprite(); (sprite&&sprite->initWithfile(filename)) { sprite->autorelease(); sprite; } CC_SAFE_DELETE(sprite); nullptr; } Rect&rect) { )FilterSprite(); (sprite&&sprite->initWithfile(filename,rect)) { sprite->autorelease(); sprite; } CC_SAFE_DELETE(sprite); nullptr; } FilterSprite*FilterSprite::createWithTexture(Texture2D*pTexture) { )FilterSprite(); Rectrect=Rect::ZERO; rect.size=pTexture->getContentSize(); (sprite&&sprite->initWithTexture(pTexture,rect)) { sprite->autorelease(); sprite; } CC_SAFE_DELETE(sprite); nullptr; } FilterSprite*FilterSprite::createWithTexture(Texture2D*texture,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">rotated) { )FilterSprite(); @H_301_1059@ (sprite&&sprite->initWithTexture(texture,rect)) { sprite->autorelease(); sprite; } CC_SAFE_DELETE(sprite); nullptr; } FilterSprite*FilterSprite::createWithSpriteFrame(SpriteFrame*spriteFrame) { )FilterSprite(); (sprite&&spriteFrame&&sprite->initWithSpriteFrame(spriteFrame)) { sprite->autorelease(); sprite; } CC_SAFE_DELETE(sprite); nullptr; } FilterSprite*FilterSprite::createWithSpriteFramename( std::string&spriteFramename) { SpriteFrame*frame=SpriteFrameCache::getInstance()->getSpriteFrameByname(spriteFramename); # COCOS2D_DEBUG>0 char msg[256]={0}; sprintf (msg, "InvalIDspriteFramename:%s" CCASSERT(frame!=nullptr,msg); #endif createWithSpriteFrame(frame); } FilterSprite::initWithTexture(Texture2D*pTexture,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">Rect&tRect){ do { CC_BREAK_IF(!Sprite::initWithTexture(pTexture,tRect)); GLchar*pszFragSource= "#ifdefGL_ES\n\ ;\n\ #endif\n\ uniformsampler2Du_texture;\n\ varyingvec2v_texCoord;\n\ varyingvec4v_fragmentcolor;\n\ uniformmat4fiterMat;\n\ )\n\ {\n\ gl_Fragcolor=fiterMat*value;\n\ }"; @H_403_1265@ autoglprogram=GLProgram::createWithByteArrays(ccpositionTexturecolor_vert,pszFragSource); autoglprogramstate=GLProgramState::getorCreateWithGLProgram(glprogram); setGLProgramState(glprogramstate); CHECK_GL_ERROR_DEBUG(); return true ; } while (0); ; } FilterSprite::setFilterMat(cocos2d::Mat4matrixArray) { m_uSpriteFilter=matrixArray; } FilterSprite::draw(Renderer*renderer,uint32_tflags) { _customCommand.init(_globalZOrder); _customCommand.func=CC_CALLBACK_0(FilterSprite::onDraw,153)!important; background:none!important">this renderer->addCommand(&_customCommand); } FilterSprite::onDraw( { autoglProgramState=getGLProgramState(); glProgramState->apply(transform); GL::blendFunc(_blendFunc.src,_blendFunc.dst); GL::bindTexture2D(_texture->getname()); GL::enabLevertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_color_TEX); #definekQuadSize sizeof (_quad.bl) @H_461_1404@ size_t offset=( )&_quad; //vertex int diff=offsetof(V3F_C4B_T2F,vertices); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_position,3,GL_float,GL_FALSE,kQuadSize,( *)(offset+diff)); //texCoods glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,2,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">*)(offset+diff)); //color glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_color,4,GL_UNSIGNED_BYTE,GL_TRUE,monospace!important; Font-size:1em!important; min-height:inherit!important; background:none!important">*)(offset+diff)); glDrawArrays(GL_TRIANGLE_STRIP,4); CHECK_GL_ERROR_DEBUG(); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4); }


来源网址:http://www.cocoachina.com/bbs/read.php?tid-238457.html

分享到: 赞(0) 文章评论 (3) tjunxin @H_601_1502@2014-12-11 15:07:22 是不是直接继承自sprite的类想用shader都要重写draw啊? @L_502_7@ 回复(0) q312998164 @H_601_1502@2014-11-12 10:23:01 Reference to 'Rect' is ambiguous ? 这是什么错误呀 zxcvbnm0014 @H_601_1502@2014-11-11 17:16:33 Node下有个setcolor函数 实现的就是这种效果。拿setcolor传入参数 乘于像素的颜色 得到最终的效果 总结

以上是内存溢出为你收集整理的在Cocos2d-x v3.x 中实现带颜色滤镜的Sprite全部内容,希望文章能够帮你解决在Cocos2d-x v3.x 中实现带颜色滤镜的Sprite所遇到的程序开发问题。

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

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

原文地址: http://outofmemory.cn/web/1026235.html

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

发表评论

登录后才能评论

评论列表(0条)

保存