[cocos2d-x]对CCSprite进行高斯模糊
摘要 cocos2d-x 2.2.1 中没有直接用于模糊精灵的类,但是在TestCpp里面的ShaderTest实现了高斯模糊。于是直接搬过来用就行了。
cocos2d-x 高斯模糊 精灵 blur
你可以从下面的目录找到示例的源代码:
cocos2d-x-2.2.1\samples\Cpp\TestCpp\Classes\ShaderTest
SpriteBlur类用于实现高斯模糊,但并没有定义在ShaderTest.h中,打开ShaderTest.cpp,大概在488行有这个类的定义和实现:
01
| // ShaderBlur
|
02
|
03
| class SpriteBlur : public CCSprite
|
04
| {
|
05
| public :
|
06
| ~SpriteBlur();
|
07
| void setBlurSize( float f);
|
08
| bool initWithTexture(CCTexture2D* texture, const CCRect& rect);
|
09
| void draw();
|
10
| void initProgram();
|
11
| void listenBackToForeground(CCObject *obj);
|
12
|
13
| static SpriteBlur* create( const char *pszFileName);
|
14
|
15
| CCPoint blur_;
|
16
| GLfloat sub_[4];
|
17
|
18
| GLuint blurLocation;
|
19
| GLuint subLocation;
|
20
| };
|
实现:
001
| SpriteBlur::~SpriteBlur()
|
002
| {
|
003
| CCNotificationCenter::sharedNotificationCenter()->removeObserver( this , EVENT_COME_TO_FOREGROUND);
|
004
| }
|
005
|
006
| SpriteBlur* SpriteBlur::create( const char *pszFileName)
|
007
| {
|
008
| SpriteBlur* pRet = new SpriteBlur();
|
009
| if (pRet && pRet->initWithFile(pszFileName))
|
010
| {
|
011
| pRet->autorelease();
|
012
| }
|
013
| else
|
014
| {
|
015
| CC_SAFE_DELETE(pRet);
|
016
| }
|
017
| |
018
| return pRet;
|
019
| }
|
020
|
021
| void SpriteBlur::listenBackToForeground(CCObject *obj)
|
022
| {
|
023
| setShaderProgram(NULL);
|
024
| initProgram();
|
025
| }
|
026
|
027
| bool SpriteBlur::initWithTexture(CCTexture2D* texture, const CCRect& rect)
|
028
| {
|
029
| if ( CCSprite::initWithTexture(texture, rect) )
|
030
| {
|
031
| CCNotificationCenter::sharedNotificationCenter()->addObserver( this ,
|
032
| callfuncO_selector(SpriteBlur::listenBackToForeground),
|
033
| EVENT_COME_TO_FOREGROUND,
|
034
| NULL);
|
035
| |
036
| CCSize s = getTexture()->getContentSizeInPixels();
|
037
|
038
| blur_ = ccp(1/s.width, 1/s.height);
|
039
| sub_[0] = sub_[1] = sub_[2] = sub_[3] = 0;
|
040
|
041
| this ->initProgram();
|
042
| |
043
| return true ;
|
044
| }
|
045
|
046
| return false ;
|
047
| }
|
048
|
049
| void SpriteBlur::initProgram()
|
050
| {
|
051
| GLchar * fragSource = (GLchar*) CCString::createWithContentsOfFile(
|
052
| CCFileUtils::sharedFileUtils()->fullPathForFilename( "Shaders/example_Blur.fsh" ).c_str())->getCString();
|
053
| CCGLProgram* pProgram = new CCGLProgram();
|
054
| pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, fragSource);
|
055
| setShaderProgram(pProgram);
|
056
| pProgram->release();
|
057
| |
058
| CHECK_GL_ERROR_DEBUG();
|
059
| |
060
| getShaderProgram()->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
|
061
| getShaderProgram()->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
|
062
| getShaderProgram()->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
|
063
| |
064
| CHECK_GL_ERROR_DEBUG();
|
065
| |
066
| getShaderProgram()->link();
|
067
| |
068
| CHECK_GL_ERROR_DEBUG();
|
069
| |
070
| getShaderProgram()->updateUniforms();
|
071
| |
072
| CHECK_GL_ERROR_DEBUG();
|
073
| |
074
| subLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "substract" );
|
075
| blurLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "blurSize" );
|
076
| |
077
| CHECK_GL_ERROR_DEBUG();
|
078
| }
|
079
|
080
| void SpriteBlur::draw()
|
081
| {
|
082
| ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex );
|
083
| ccBlendFunc blend = getBlendFunc();
|
084
| ccGLBlendFunc(blend.src, blend.dst);
|
085
|
086
| getShaderProgram()->use();
|
087
| getShaderProgram()->setUniformsForBuiltins();
|
088
| getShaderProgram()->setUniformLocationWith3f(blurLocation, blur_.x, blur_.y);
|
089
| getShaderProgram()->setUniformLocationWith5fv(subLocation, sub_, 1);
|
090
|
091
| ccGLBindTexture2D( getTexture()->getName());
|
092
|
093
| //
|
094
| // Attributes
|
095
| //
|
096
| #define kQuadSize sizeof(m_sQuad.bl)
|
097
| long offset = ( long )&m_sQuad;
|
098
|
099
| // vertex
|
100
| int diff = offsetof( ccV3F_C4B_T2F, vertices);
|
101
| glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, ( void *) (offset + diff));
|
102
|
103
| // texCoods
|
104
| diff = offsetof( ccV3F_C4B_T2F, texCoords);
|
105
| glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, ( void *)(offset + diff));
|
106
|
107
| // color
|
108
| diff = offsetof( ccV3F_C4B_T2F, colors);
|
109
| glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, ( void *)(offset + diff));
|
110
|
111
|
112
| glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
113
|
114
| CC_INCREMENT_GL_DRAWS(1);
|
115
| }
|
116
|
117
| void SpriteBlur::setBlurSize( float f)
|
118
| {
|
119
| CCSize s = getTexture()->getContentSizeInPixels();
|
120
|
121
| blur_ = ccp(1/s.width, 1/s.height);
|
122
| blur_ = ccpMult(blur_,f);
|
123
| }
|
好了,直接copy到你的program里面,不过有一点需要注意,就是他这个只能用一个文件(图片)create,如果需要用一个Texture初始化(因为有时候需要模糊即时的sprite),可以稍微改装一下,加一个函数:
1
| static SpriteBlur* createWithTexture(CCTexture2D *pTexture);
|
实现:
01
| SpriteBlur* SpriteBlur::createWithTexture(CCTexture2D *pTexture)
|
02
| {
|
03
| CCAssert(pTexture != NULL, "Invalid texture for sprite" );
|
04
|
05
| CCRect rect = CCRectZero;
|
06
| rect.size = pTexture->getContentSize();
|
07
|
08
| SpriteBlur* pRet = new SpriteBlur();
|
09
| if (pRet && pRet->initWithTexture(pTexture,rect))
|
10
| {
|
11
| pRet->autorelease();
|
12
| }
|
13
| else
|
14
| {
|
15
| CC_SAFE_DELETE(pRet);
|
16
| }
|
17
| |
18
| return pRet;
|
19
| }
|
用法:
1
| SpriteBlur *bluredSpr = SpriteBlur::createWithTexture(tex);
|
2
| bluredSpr->setPosition(ccp(sz.width/2,sz.height/2));
|
3
| bluredSpr->setBlurSize(0.9f); // 这里稍微设小一点
|
4
| addChild(bluredSpr);
|
效果:
注意:
他需要一个fsh文件(具体看它的实现),似乎是叠texture用的,找到example_Blur.fsh放到你的Resources\Shaders目录下