-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9f2216c
commit 430890a
Showing
11 changed files
with
568 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
#include "FilterNode.h" | ||
#include "cocos-ext.h" | ||
|
||
FilterNode::FilterNode():_srcNode(NULL) | ||
{ } | ||
|
||
FilterNode::~FilterNode() | ||
{ | ||
CCLog("------------"); | ||
} | ||
|
||
CCGLProgram* FilterNode::commonPrograme(const GLchar* src) | ||
{ | ||
CCGLProgram* pp = new CCGLProgram(); | ||
if (pp) { | ||
pp->initWithVertexShaderByteArray(ccPositionTextureColor_vert, src); | ||
pp->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position); | ||
pp->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color); | ||
pp->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords); | ||
pp->link(); | ||
pp->updateUniforms(); | ||
} | ||
return pp; | ||
} | ||
|
||
FilterNode* FilterNode::create(CCNode* src, const CCSize& size) | ||
{ | ||
FilterNode* ret = new FilterNode(); | ||
if (ret && ret->init(src, size)) { | ||
ret->autorelease(); | ||
return ret; | ||
} else { | ||
CC_SAFE_RELEASE(ret); | ||
return NULL; | ||
} | ||
} | ||
|
||
bool FilterNode::init(CCNode* src, const CCSize& size) | ||
{ | ||
bool bRet = false; | ||
do { | ||
if (_srcNode) { | ||
CCLog("init can only be called once!"); | ||
} | ||
CC_BREAK_IF(!CCRenderTexture::initWithWidthAndHeight(size.width, size.height, | ||
kCCTexture2DPixelFormat_RGBA8888)); | ||
_srcNode = src; | ||
if (_srcNode) | ||
_pos = _srcNode->getPosition(); | ||
else | ||
_pos = CCPointZero; | ||
bRet = true; | ||
}while(0); | ||
return bRet; | ||
} | ||
|
||
void FilterNode::capture() | ||
{ | ||
if (!_srcNode){ return; } | ||
CCPoint pos = _srcNode->getPosition(); | ||
CCPoint ar = _srcNode->getAnchorPoint(); | ||
_pos = ccpSub(pos, _pos); | ||
_srcNode->setPosition(ar.x * _srcNode->getContentSize().width, ar.y * _srcNode->getContentSize().height); | ||
this->beginWithClear(0, 0, 0, 0); | ||
_srcNode->visit(); | ||
this->end(); | ||
_srcNode->setPosition(pos); | ||
this->getSprite()->setPosition(ccpAdd(this->getSprite()->getPosition(), _pos)); | ||
_pos = pos; | ||
} | ||
|
||
/*********************| GuassianBlur class |*********************/ | ||
static GLchar* hblurSrc = NULL; | ||
static GLchar* vblurSrc = NULL; | ||
static GaussianBlur* _scSizeBlurNode = NULL; | ||
|
||
GaussianBlur::GaussianBlur():f1(NULL), f2(NULL), _showing(false) | ||
{ } | ||
|
||
GaussianBlur::~GaussianBlur() | ||
{ | ||
CC_SAFE_RELEASE_NULL(f1); | ||
CC_SAFE_RELEASE_NULL(f2); | ||
} | ||
|
||
bool GaussianBlur::do_ready() | ||
{ | ||
unsigned long l = 0; | ||
unsigned char* data = NULL; | ||
if (!hblurSrc) { | ||
hblurSrc = (GLchar*)CCFileUtils::sharedFileUtils()->getFileData("shaders/hblur.fsh", "rb", &l); | ||
hblurSrc[l] = 0; | ||
} | ||
if (!vblurSrc) { | ||
vblurSrc = (GLchar*)CCFileUtils::sharedFileUtils()->getFileData("shaders/vblur.fsh", "rb", &l); | ||
vblurSrc[l] = 0; | ||
} | ||
screenBlurNodeInstance(); | ||
return hblurSrc && vblurSrc; | ||
} | ||
|
||
void GaussianBlur::do_free() | ||
{ | ||
CC_SAFE_DELETE_ARRAY(hblurSrc); | ||
CC_SAFE_DELETE_ARRAY(vblurSrc); | ||
CC_SAFE_RELEASE_NULL(_scSizeBlurNode); | ||
} | ||
|
||
GaussianBlur*GaussianBlur::create(CCNode* src, const CCSize& size) | ||
{ | ||
GaussianBlur* ret = new GaussianBlur(); | ||
if (ret && ret->init(src, size)) { | ||
ret->autorelease(); | ||
return ret; | ||
} else { | ||
CC_SAFE_DELETE(ret); | ||
return NULL; | ||
} | ||
} | ||
|
||
GaussianBlur*GaussianBlur::screenBlurNodeInstance() | ||
{ | ||
if (_scSizeBlurNode) | ||
return _scSizeBlurNode; | ||
_scSizeBlurNode = new GaussianBlur(); | ||
_scSizeBlurNode->retain(); | ||
_scSizeBlurNode->init(NULL, CCDirector::sharedDirector()->getVisibleSize(), true); | ||
return _scSizeBlurNode; | ||
} | ||
|
||
bool GaussianBlur::init(CCNode* src, const CCSize& size, bool reused) | ||
{ | ||
bool bRet = false; | ||
do { | ||
CC_BREAK_IF(!CCNode::init()); | ||
f1 = FilterNode::create(src, size); | ||
CC_BREAK_IF(!f1); | ||
f1->retain(); | ||
CCGLProgram* s = FilterNode::commonPrograme(hblurSrc); | ||
f1->filter(s); | ||
setBlurSize(size, 1); | ||
f1->capture(); | ||
s->release(); | ||
|
||
f2 = FilterNode::create(f1->getSprite(), size); | ||
CC_BREAK_IF(!f2); | ||
s = FilterNode::commonPrograme(vblurSrc); | ||
f2->filter(s); | ||
setBlurSize(size, 2); | ||
f2->retain(); | ||
f2->capture(); | ||
s->release(); | ||
|
||
this->setContentSize(size); | ||
this->setAnchorPoint(CCPointZero); | ||
this->setPosition(CCPointZero); | ||
f2->setPosition(size.width /2, size.height/2); | ||
this->addChild(f2); | ||
|
||
bRet = true; | ||
}while(0); | ||
return bRet; | ||
} | ||
|
||
void GaussianBlur::setBlurSize(const CCSize& size, const int which , GLfloat ratio) | ||
{ | ||
CCGLProgram* s = NULL; | ||
GLint blurSLoc = 0; | ||
if (!which || 1 == which) { | ||
s = f1->getSprite()->getShaderProgram(); | ||
blurSLoc = glGetUniformLocation(s->getProgram(), "ratio"); | ||
s->setUniformLocationWith1f(blurSLoc, ratio); | ||
blurSLoc = glGetUniformLocation(s->getProgram(), "hsize"); | ||
s->setUniformLocationWith1f(blurSLoc, (GLfloat)(size.width)); | ||
} | ||
if (!which || 2 == which) { | ||
s = f2->getSprite()->getShaderProgram(); | ||
blurSLoc = glGetUniformLocation(s->getProgram(), "ratio"); | ||
s->setUniformLocationWith1f(blurSLoc, ratio); | ||
blurSLoc = glGetUniformLocation(s->getProgram(), "vsize"); | ||
s->setUniformLocationWith1f(blurSLoc, (GLfloat)(size.height)); | ||
} | ||
} | ||
|
||
bool GaussianBlur::reset(CCNode* src) | ||
{ | ||
f1->changeNode(src); | ||
f2->changeNode(f1->getSprite()); | ||
} | ||
|
||
void GaussianBlur::cleanFromWorld() | ||
{ | ||
realtime(false); | ||
this->removeFromParent(); | ||
this->removeAllChildren(); | ||
this->addChild(f2); | ||
_showing = false; | ||
} | ||
|
||
void GaussianBlur::show() | ||
{ | ||
if (_showing) return; | ||
CCScene* s =CCDirector::sharedDirector()->getRunningScene(); | ||
if (s) { | ||
_showing = true; | ||
s->addChild(this); | ||
} | ||
} | ||
|
||
void GaussianBlur::capture() | ||
{ | ||
f1->capture(); | ||
f2->capture(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#ifndef FILETERSPRITE_H | ||
#define FILETERSPRITE_H | ||
|
||
/** | ||
* Desc: 特效node | ||
* Auth: 张宇飞 | ||
* Date: 2014-08-19 | ||
*/ | ||
|
||
#include "cocos2d.h" | ||
USING_NS_CC; | ||
|
||
class FilterProto | ||
{ | ||
public: | ||
FilterProto():_rt(false) {} | ||
virtual void capture() = 0; | ||
virtual void updateCapture(bool b) = 0; | ||
void realtime(bool b) { | ||
if (b != _rt) { | ||
_rt = b; | ||
updateCapture(b); | ||
} | ||
} | ||
inline bool isRealTime() {return _rt;} | ||
private: | ||
bool _rt; | ||
}; | ||
|
||
#define UPCAP_FUNC(_cls_, _freshfunc_) \ | ||
void updateCapture(bool b) { \ | ||
if (b) \ | ||
this->schedule(schedule_selector(_cls_::_freshfunc_)); \ | ||
else \ | ||
this->unschedule(schedule_selector(_cls_::_freshfunc_));\ | ||
} | ||
|
||
/** | ||
* @brief The FilterNode class | ||
*/ | ||
class FilterNode : public CCRenderTexture, public FilterProto | ||
{ | ||
public: | ||
FilterNode(); | ||
~FilterNode(); | ||
public: | ||
static CCGLProgram* commonPrograme(const GLchar* src); | ||
static FilterNode* create(CCNode* src, const CCSize& size); | ||
inline static FilterNode* create(CCNode* src) { | ||
if (src) return create(src, src->getContentSize()); | ||
return NULL; | ||
} | ||
public: | ||
bool init(CCNode* src, const CCSize& size); | ||
/* set filter */ | ||
inline void filter(CCGLProgram* shader) { | ||
this->getSprite()->setShaderProgram(shader); | ||
} | ||
inline void changeNode(CCNode* src) {_srcNode = src; capture();} | ||
|
||
/* take a capture means do draw elements once 快照 */ | ||
void capture(); | ||
UPCAP_FUNC(FilterNode, freshCapture) | ||
private: | ||
void freshCapture(float dt) { capture();} | ||
private: | ||
CCNode* _srcNode; | ||
CCPoint _pos; | ||
}; | ||
|
||
/** | ||
* @brief The GaussianBlur class use two FilterNode, one with horizontal blur and | ||
* send result to next FilerNode with vertical blur .Then sencond result will show | ||
* as Gaussian blur effect | ||
* 中文:这个类用了两个FilterNode来实现高斯模糊。第一个用横向的模糊,结果作为第二个的 | ||
* 输入进行纵向模糊,得到的结果就是需要的了。 | ||
*/ | ||
class GaussianBlur : public CCNode, public FilterProto | ||
{ | ||
public: | ||
GaussianBlur(); | ||
~GaussianBlur(); | ||
public: | ||
/* call this at global init time */ | ||
static bool do_ready(); | ||
/* call this at global end time */ | ||
static void do_free(); | ||
|
||
static GaussianBlur* create(CCNode* src, const CCSize& size); | ||
inline static GaussianBlur* create(CCNode* src) { | ||
if (src) return create(src, src->getContentSize()); | ||
return NULL; | ||
} | ||
/** | ||
* @brief screenBlurNode get a blur node instance with screen size(中文:获取一个屏幕大小的模糊单例) | ||
*/ | ||
static GaussianBlur* screenBlurNodeInstance(); | ||
public: | ||
bool init(CCNode* src, const CCSize& size, bool reused = false); | ||
/** | ||
* @brief setBlurSize 设置模糊程度 | ||
* @param size 模糊范围 | ||
* @param which 0 all , 1 horizontal blur, 2 vertical blur(中文:0横纵向同时模糊,1横向模糊设定,2纵向模糊设定) | ||
* @param ratio 模糊半径 | ||
*/ | ||
void setBlurSize(const CCSize& size, const int which = 0, GLfloat ratio = 3.0); | ||
bool reset(CCNode* src); | ||
void cleanFromWorld(); | ||
/* @brief show try use runningScene()->addChild to show this(中文:尝试用getRunningScene()->addChild来显示当前节点 */ | ||
void show(); | ||
void capture(); | ||
UPCAP_FUNC(GaussianBlur, freshCapture) | ||
private: | ||
void freshCapture(float dt) { capture();} | ||
private: | ||
FilterNode *f1, *f2; | ||
bool _showing; | ||
}; | ||
|
||
#endif // FILETERSPRITE_H |
Oops, something went wrong.