摘要  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行有这个类的定义和实现:

	// 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
};


实现:

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()->setUniformLocationWith2f(blurLocation, blur_.x, blur_.y);
089
    getShaderProgram()->setUniformLocationWith4fv(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),可以稍微改装一下,加一个函数:


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
}


用法:


	SpriteBlur *bluredSpr = SpriteBlur::createWithTexture(tex);
2
bluredSpr->setPosition(ccp(sz.width/2,sz.height/2));
3
bluredSpr->setBlurSize(0.9f); // 这里稍微设小一点
4
addChild(bluredSpr);

效果:

[cocos2d-x]对CCSprite进行高斯模糊_初始化

注意:

他需要一个fsh文件(具体看它的实现),似乎是叠texture用的,找到example_Blur.fsh放到你的Resources\Shaders目录下