http://www.dreamfairy.cn/blog/index.PHP/2014/06/26/multi-filter-in-cocos2dx-2-x-like-sprite-in-as.html
可以通过网盘下载gif看看动态效果
http://pan.baidu.com/s/1jGoRER0
也可以看看移植前的stage3D版本的效果
http://www.dreamfairy.cn/blog/index.php/2014/05/10/create-a-god-ray-effect-in-stage3d.html
又一个月没写博客了,先吐槽下,怎么广告这么多。。。 每天都要删,插件都顶不住了。
然后再吐槽下之前某网友好像是叫as3er的看了我的god ray教程,然后自己在away3d中实现了但是缺少了遮挡这个god ray中最体现效果的功能。 这先不说,这位同学看就看了,理解了就好了嘛,反而不满我不发源码~ 我也不知道该说啥 摊手. 国内的开源社区条件是一直很恶劣的,以前我也完整开源,现在只能有选择的开源了,我还没有那么伟大到不用考虑薪水问题,而无私贡献。之前廖成在 Particle 做的 幻影和热流效果就不开源,我做了详细的讲解但也不开源,没有必要跟他人起矛盾,但我觉得对于有经验的程序员这些讲解已经足够了。
回归正题,cocos2dx纯粹的代码堆积,毫无美感,这是用了一段时间的体会,API的不稳定也是大忌,有点赞同云风大叔的想法了。 最近要在 CCSprite 上做各种效果,以网络上的教程来说,只能创建多个 自定义CCSprite,每个特定滤镜,最后不断切换。。。 对于从AS毕业的我来说,太坑了。
于是打算实现带滤镜接口的CCSprite,我没有一部分程序员的毛病,比如重复造轮子,触控的程序员估计大部分都有这毛病,看看cocos2dx中大量的重复功能函数库。 于是找到了 zrong 同学写的 CCFilteredSprite github 上在这里
https://github.com/zrong/cocos2d-x-filters 而且这货在 quick 和 cocos2dx 3.x 中貌似继承了。 由于我不想装win8,所以用不了 3.x,因为是开发弹幕游戏,担心lua顶不住,不能用quick. 又因为项目是用 cocos2dx 2.2.4 搞的,这个库不完全兼容,所以只能做修改或者重写了。
我试着重现AS3 的 多个滤镜,但是 cocos2dx 在 2.x 版本对于 renderTexture 的封装。。。无力吐槽, 要实现仅能大改了,于是放弃了这个想法,还是单个滤镜吧。
接下来上代码
核心类 只有2个 CCSpriteWithFilter.cpp 和 CCFilter.cpp
所有的滤镜都是继承自 CCFilter.cpp
那么从头开始
首先创建头文件 CCSpriteWithFilter.h
1
2 3 4 5 6 7 8 9 10 11 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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
/******************************************************************
Copyright (c) 2014,dreamfairy.cn All rights reserved 创建日期: 2014年6月26日 16时33分 文件名称: CCSpriteWidthFilter.h 说 明: 当前版本: 1.00 作 者: 苍白的茧 概 述: *******************************************************************/ #ifndef __CCspriteWithFilter__ #define __CCspriteWithFilter__ #include "cocos2d.h" #include "filter/CCFilter.h" class CCFilter; USING_NS_CC; class CCSpriteWidthFilter : public CCSprite { public: CCSpriteWidthFilter(); ~CCSpriteWidthFilter(); static CCSpriteWidthFilter* create(); static CCSpriteWidthFilter* create(const char* $pszFileName); static CCSpriteWidthFilter* create(const char* $pszFileName,const CCRect& $rect); static CCSpriteWidthFilter* createWithTexture(CCTexture2D* $pTexture); static CCSpriteWidthFilter* createWithTexture(CCTexture2D* $pTexture,const CCRect& rect); static CCSpriteWidthFilter* createWithSpriteFrame(CCSpriteFrame* $pSpriteFrame); static CCSpriteWidthFilter* createWithSpriteFrameName(const char* $pszSpriteFrameName); virtual void draw(void); virtual CCFilter* getFilter(unsigned int index = 0); virtual void setFilter(CCFilter* filter); virtual CCArray* getFilters(); virtual void setFilters(CCArray* filters); virtual void clearFilter(); protected: virtual void drawFilter(); virtual bool updateFilters(); CCArray* m_filters; }; #endif |
#include "CCSpriteWidthFilter.h"
#include "ccMacros.h" voidCCSpriteWidthFilter :: draw ( ) { CCObject *obj ; CCARRAY_FOREACH (m_filters,obj ) { CCFilter *filter = static_cast <CCFilter * > (obj ) ; CC_PROFILER_START_CATEGORY (kCCProfilerCategorySprite,"CCSprite - draw" ) ; CCAssert ( @H_552_502@!m_pobBatchNode,48)">"If CCSprite is being rendered by CCSpriteBatchNode,CCSprite#draw SHOULD NOT be called" ) ; this - >setShaderProgram (filter - >getProgram ( ) ) ; do { ccGLEnable (m_eGLServerState ) ; CCAssert (getShaderProgram ( ),48)">"No shader program set for this node" ) ; { getShaderProgram ( ) - >use ( ) ; getShaderProgram ( ) - >setUniformsForBuiltins ( ) ; } } while ( 0 ) ; //useProgram后调用draw filter - >draw ( ) ; ccGLBlendFunc (m_sBlendFunc. src,m_sBlendFunc. dst ) ; ccGLBindTexture2D (m_pobTexture - >getName ( ) ) ; ccGLEnableVertexAttribs (kCCVertexAttribFlag_PosColorTex ) ; #define kQuadSize sizeof(m_sQuad.bl) #ifdef EMSCRIPTEN longoffset = 0 ; setGLBufferData ( @H_552_502@&m_sQuad,4 *kQuadSize,160)">0 ) ; #else = ( long ) @H_552_502@&m_sQuad ; #endif // EMSCRIPTEN // vertex intdiff = offsetof (ccV3F_C4B_T2F,vertices ) ; glVertexAttribPointer (kCCVertexAttrib_Position,160)">3,GL_FLOAT,GL_FALSE,kQuadSize,( void * ) (offset +diff ) ) ; // texCoods diff ) ; glVertexAttribPointer (kCCVertexAttrib_TexCoords,160)">2,64)">// color diff ) ; glVertexAttribPointer (kCCVertexAttrib_Color,160)">4,GL_UNSIGNED_BYTE,GL_TRUE,128)">void * ) (offset +diff ) ) ; glDrawArrays (GL_TRIANGLE_STRIP,160)">0,160)">4 ) ; CHECK_GL_ERROR_DEBUG ( ) ; #if CC_SPRITE_DEBUG_DRAW == 1 // draw bounding Box CCPoint vertices [ 4 ] = { ccp (m_sQuad. tl. vertices. x,m_sQuad. y ), ccp (m_sQuad. bl. br. tr. } ; ccDrawPoly (vertices,true ) ; #elif CC_SPRITE_DEBUG_DRAW == 2 // draw texture Box CCSize s =this - >getTextureRect ( ). size ; CCPoint offsetPix >getOffsetPosition ( ) ; CCPoint vertices [ = { ccp (offsetPix. (offsetPix. x +s. width, ccp (offsetPix. y +s. height ),255)">height ) } ; ccDrawPoly (vertices,64)">#endif // CC_SPRITE_DEBUG_DRAW CC_INCREMENT_GL_DRAWS ( 1 ) ; CC_PROFILER_STOP_CATEGORY (kCCProfilerCategorySprite,48)">"CCSprite - draw" ) ; } } drawFilter ( ) { if (m_filters @H_552_502@&&m_filters - >count ( ) == 1 ) { > (m_filters - >objectAtIndex ( 0 ) ) - >draw ( ) ; } } //以push的方式增加filter setFilter (CCFilter *filter ) { if (m_filters - >indexOfObject (filter ) == UINT_MAX ) { m_filters - >addObject (filter ) ; filter - >initSprite ( this ) ; } } clearFilter ( ) { //todo } boolCCSpriteWidthFilter :: updateFilters ( ) { return true ; } CCFilter *CCSpriteWidthFilter :: getFilter ( unsigned intindex /*= 0*/ ) { >objectAtIndex (index ) ) ; } CCSpriteWidthFilter *CCSpriteWidthFilter :: create ( ) { CCSpriteWidthFilter *sprite newCCSpriteWidthFilter ( ) ; if (sprite @H_552_502@&&sprite - >init ( ) ) { sprite - >autorelease ( ) ; returnsprite ; } CC_SAFE_DELETE (sprite ) ; NULL ; } CCSpriteWidthFilter *CCSpriteWidthFilter :: create ( const char *$pszFileName ) { CCSpriteWidthFilter *sprite >initWithFile ($pszFileName ) ) { sprite - returnsprite ; } else { CC_SAFE_DELETE (sprite ) ; NULL ; } } CCSpriteWidthFilter *CCSpriteWidthFilter :: char *$pszFileName,constCCRect @H_552_502@&$rect ) { CCSpriteWidthFilter *sprite >initWithFile ($pszFileName,$rect ) ) { sprite - createWithTexture (CCTexture2D *$pTexture ) { CCSpriteWidthFilter *sprite >initWithTexture ($pTexture ) ) { sprite - createWithTexture (CCTexture2D *$pTexture,128)">constCCRect @H_552_502@&rect ) { CCSpriteWidthFilter *sprite >initWithTexture ($pTexture,rect ) ) { sprite - createWithSpriteFrame (CCSpriteFrame *$pSpriteFrame ) { CCSpriteWidthFilter *sprite if ($pSpriteFrame @H_552_502@&&sprite ) { if ($pSpriteFrame - >isRotated ( ) ) { CCSprite *__sp =CCSprite :: createWithSpriteFrame ($pSpriteFrame ) ; CCSize __size =__sp - >getContentSize ( ) ; __sp - >setAnchorPoint (ccp ( 0 ) ) ; __sp - >setPosition (ccp ( 0 ) ) ; CCRenderTexture *__rTex =CCRenderTexture :: create (__size. height ) ; __rTex - >begin ( ) ; __sp - >visit ( ) ; __rTex - >end ( ) ; CCTexture2D *__newTex newCCTexture2D ( ) ; __newTex - >initWithImage (__rTex - >newCCImage ( true ) ) ; __newTex - >autorelease ( ) ; sprite - >initWithTexture (__newTex ) ; //CCLOG("==== CCFilteredSprite::initWithTexture,rotated true texture wh(%f,%f)",__newTex->getContentSize().width,__newTex->getContentSize().height); } else { sprite - >initWithSpriteFrame ($pSpriteFrame ) ; } sprite - createWithSpriteFrameName ( char *$pszSpriteFrameName ) { CCSpriteFrame *pFrame =CCSpriteFrameCache :: sharedSpriteFrameCache ( ) - >spriteFrameByName ($pszSpriteFrameName ) ; #if COCOS2D_DEBUG > 0 charmsg [ 256 ] = { 0 } ; sprintf (msg,48)">"Invalid spriteFrameName: %s",$pszSpriteFrameName ) ; CCAssert (pFrame @H_552_502@! NULL,msg ) ; #endif returncreateWithSpriteFrame (pFrame ) ; } CCSpriteWidthFilter :: CCSpriteWidthFilter ( ) { m_filters =CCArray :: create ( ) ; m_filters - >retain ( ) ; } CCSpriteWidthFilter ::~CCSpriteWidthFilter ( ) { m_filters - >release ( ) ; //CC_SAFE_DELETE(m_filters); } setFilters (CCArray *filters ) { CCObject *obj ; CCARRAY_FOREACH (filters,obj ) { CCFilter *addFilter > (obj ) ; addFilter - this ) ; } m_filters - >addObjectsFromArray (filters ) ; } CCArray *CCSpriteWidthFilter :: getFilters ( ) { returnm_filters ; } |
@H_403_167@
#ifndef __CCFILTER__
#define __CCFILTER__ #include "cocos2d.h" #include "CCGL.h" #include "CCSpriteWidthFilter.h" classCCSpriteWidthFilter ; USING_NS_CC ; classCCFilter : publicCCObject { public : CCFilter ( ) ; ~CCFilter ( ) ; virtual voidinitSprite (CCSpriteWidthFilter *sprite ) ; voiddraw ( ) ; CCGLProgram *getProgram ( ) ; char *shaderName ; protected : CCGLProgram *m_program ; voidinitProgram ( ) ; virtualCCGLProgram *loadShader ( ) ; voidsetAttributes (CCGLProgram *gl ) ; voidsetUniforms (CCGLProgram *gl ) ; CCSpriteWidthFilter *m_sprite ; } ; #endif |
@H_403_167@
#include "CCFilter.h"
CCFilter :: CCFilter ( ) :shaderName ( NULL ), m_program ( NULL ) { } CCFilter ::~CCFilter ( ) { } voidCCFilter :: initSprite (CCSpriteWidthFilter *sprite ) { } draw ( ) { } CCGLProgram *CCFilter :: getProgram ( ) { returnm_program ; } initProgram ( ) { CCGLProgram *program =CCShaderCache :: sharedShaderCache ( ) - >programForKey (this - >shaderName ) ; if ( @H_552_502@!program ) { program =loadShader ( ) ; this - >setAttributes (program ) ; CHECK_GL_ERROR_DEBUG ( ) ; program - >link ( ) ; CHECK_GL_ERROR_DEBUG ( ) ; program - >updateUniforms ( ) ; CHECK_GL_ERROR_DEBUG ( ) ; CCShaderCache :: >addProgram (program,this - >shaderName ) ; program - >release ( ) ; } if ( @H_552_502@!m_program ) { CCLOG ( "initProgram id:%d",program - >getProgram ( ) ) ; m_program =program ; m_program - >retain ( ) ; } } CCGLProgram *CCFilter :: loadShader ( ) { NULL ; } setAttributes (CCGLProgram *gl ) { } setUniforms (CCGLProgram *gl ) { } |
@H_403_167@
CCGodRayFilter
*filter
=CCGodRayFilter
::
create
(
)
;
CCSpriteWidthFilter *sprite =CCSpriteWidthFilter :: create ( "HelloWorld.png" ) ; sprite - >setFilter (filter ) ; //sprite->setAnchorPoint(ccp(0,0)); |
@H_403_167@
Comments (1)
虽然我没有信仰,但是万事万物都是相对的,当你觉得你没有重复造轮子的时候,自己创造CCSpriteWithFilter的时候,相对于zong同学,或者用CCFiterSprite的程序员来说,CCSpriteWithFilter就是在重复造轮子,现在你该明白为什么触控有那么多重复函数了吧,其实你自己也是一个因(相对的,我也不是吐槽,其实你的有限度的开源,我也会参考,也会用)