[cocos2d-x]对CCSprite进行高斯模糊

来源:互联网 发布:大数据安全与隐私保护 编辑:程序博客网 时间:2024/05/23 22:50
摘要 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 
03class SpriteBlur : public CCSprite
04{
05public:
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};

实现:

001SpriteBlur::~SpriteBlur()
002{
003    CCNotificationCenter::sharedNotificationCenter()->removeObserver(this, EVENT_COME_TO_FOREGROUND);
004}
005 
006SpriteBlur* 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 
021void SpriteBlur::listenBackToForeground(CCObject *obj)
022{
023    setShaderProgram(NULL);
024    initProgram();
025}
026 
027bool 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 
049void 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 
080void 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 
117void 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),可以稍微改装一下,加一个函数:

1static SpriteBlur* createWithTexture(CCTexture2D *pTexture);

实现:

01SpriteBlur* 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}


用法:

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

效果:

注意:

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


0 0