你可以从下面的目录找到示例的源代码:
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()->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),可以稍微改装一下,加一个函数:
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目录下