你可以从下面的目录找到示例的源代码:
cocos2d-x-2.2.1\samples\Cpp\TestCpp\Classes\ShaderTest
SpriteBlur类用于实现高斯模糊,但并没有定义在ShaderTest.h中,打开ShaderTest.cpp,大概在488行有这个类的定义和实现:
03 | class SpriteBlur : public CCSprite |
07 | void setBlurSize( float f); |
08 | bool initWithTexture(CCTexture2D* texture, const CCRect& rect); |
11 | void listenBackToForeground(CCObject *obj); |
13 | static SpriteBlur* create( const char *pszFileName); |
实现:
001 | SpriteBlur::~SpriteBlur() |
003 | CCNotificationCenter::sharedNotificationCenter()->removeObserver( this , EVENT_COME_TO_FOREGROUND); |
006 | SpriteBlur* SpriteBlur::create( const char *pszFileName) |
008 | SpriteBlur* pRet = new SpriteBlur(); |
009 | if (pRet && pRet->initWithFile(pszFileName)) |
015 | CC_SAFE_DELETE(pRet); |
021 | void SpriteBlur::listenBackToForeground(CCObject *obj) |
023 | setShaderProgram(NULL); |
027 | bool SpriteBlur::initWithTexture(CCTexture2D* texture, const CCRect& rect) |
029 | if ( CCSprite::initWithTexture(texture, rect) ) |
031 | CCNotificationCenter::sharedNotificationCenter()->addObserver( this , |
032 | callfuncO_selector(SpriteBlur::listenBackToForeground), |
033 | EVENT_COME_TO_FOREGROUND, |
036 | CCSize s = getTexture()->getContentSizeInPixels(); |
038 | blur_ = ccp(1/s.width, 1/s.height); |
039 | sub_[0] = sub_[1] = sub_[2] = sub_[3] = 0; |
049 | void SpriteBlur::initProgram() |
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); |
058 | CHECK_GL_ERROR_DEBUG(); |
060 | getShaderProgram()->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); |
061 | getShaderProgram()->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); |
062 | getShaderProgram()->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); |
064 | CHECK_GL_ERROR_DEBUG(); |
066 | getShaderProgram()->link(); |
068 | CHECK_GL_ERROR_DEBUG(); |
070 | getShaderProgram()->updateUniforms(); |
072 | CHECK_GL_ERROR_DEBUG(); |
074 | subLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "substract" ); |
075 | blurLocation = glGetUniformLocation( getShaderProgram()->getProgram(), "blurSize" ); |
077 | CHECK_GL_ERROR_DEBUG(); |
080 | void SpriteBlur::draw() |
082 | ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex ); |
083 | ccBlendFunc blend = getBlendFunc(); |
084 | ccGLBlendFunc(blend.src, blend.dst); |
086 | getShaderProgram()->use(); |
087 | getShaderProgram()->setUniformsForBuiltins(); |
088 | getShaderProgram()->setUniformLocationWith3f(blurLocation, blur_.x, blur_.y); |
089 | getShaderProgram()->setUniformLocationWith5fv(subLocation, sub_, 1); |
091 | ccGLBindTexture2D( getTexture()->getName()); |
096 | #define kQuadSize sizeof(m_sQuad.bl) |
097 | long offset = ( long )&m_sQuad; |
100 | int diff = offsetof( ccV3F_C4B_T2F, vertices); |
101 | glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, ( void *) (offset + diff)); |
104 | diff = offsetof( ccV3F_C4B_T2F, texCoords); |
105 | glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, ( void *)(offset + diff)); |
108 | diff = offsetof( ccV3F_C4B_T2F, colors); |
109 | glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, ( void *)(offset + diff)); |
112 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
114 | CC_INCREMENT_GL_DRAWS(1); |
117 | void SpriteBlur::setBlurSize( float f) |
119 | CCSize s = getTexture()->getContentSizeInPixels(); |
121 | blur_ = ccp(1/s.width, 1/s.height); |
122 | blur_ = ccpMult(blur_,f); |
好了,直接copy到你的program里面,不过有一点需要注意,就是他这个只能用一个文件(图片)create,如果需要用一个Texture初始化(因为有时候需要模糊即时的sprite),可以稍微改装一下,加一个函数:
1 | static SpriteBlur* createWithTexture(CCTexture2D *pTexture); |
实现:
01 | SpriteBlur* SpriteBlur::createWithTexture(CCTexture2D *pTexture) |
03 | CCAssert(pTexture != NULL, "Invalid texture for sprite" ); |
05 | CCRect rect = CCRectZero; |
06 | rect.size = pTexture->getContentSize(); |
08 | SpriteBlur* pRet = new SpriteBlur(); |
09 | if (pRet && pRet->initWithTexture(pTexture,rect)) |
用法:
1 | SpriteBlur *bluredSpr = SpriteBlur::createWithTexture(tex); |
2 | bluredSpr->setPosition(ccp(sz.width/2,sz.height/2)); |
3 | bluredSpr->setBlurSize(0.9f); |
效果:
注意:
他需要一个fsh文件(具体看它的实现),似乎是叠texture用的,找到example_Blur.fsh放到你的Resources\Shaders目录下