1、头文件:
class EffectSprite;//自定义Sprite
//
// Effect参考官方实例
//
class Effect : public Ref
{
public:
GLProgramState* getGLProgramState() const { return _glprogramstate; }
virtual void setTarget(EffectSprite *sprite){}
protected:
bool initGLProgramState(const std::string &fragmentFilename);
Effect();
virtual ~Effect();
GLProgramState *_glprogramstate;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
std::string _fragSource;
EventListenerCustom* _backgroundListener;
#endif
};
2、源文件:
class EffectSprite : public Sprite
{
public:
static EffectSprite *create(const std::string& filename) {
auto ret = new (std::nothrow) EffectSprite;
if (ret && ret->initWithFile(filename)) {
ret->autorelease();
return ret;
}
CC_SAFE_RELEASE(ret);
return nullptr;
}
void setEffect(Effect* effect) {
_defaultEffect = nullptr;
if (_defaultEffect != effect) {
effect->setTarget(this);
CC_SAFE_RELEASE(_defaultEffect);
_defaultEffect = effect;
CC_SAFE_RETAIN(_defaultEffect);
setGLProgramState(_defaultEffect->getGLProgramState());
}
}
void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override
{
#if CC_USE_CULLING
// Don't do calculate the culling if the transform was not updated
_insideBounds = (flags & FLAGS_TRANSFORM_DIRTY) ? renderer->checkVisibility(transform, _contentSize) : _insideBounds;
if (_insideBounds)
#endif
{
//normal effect: order == 0
_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform, flags);
renderer->addCommand(&_quadCommand);
}
}
protected:
Effect* _defaultEffect;
};
// Grey
class EffectGreyScale : public Effect
{
public:
CREATE_FUNC(EffectGreyScale);
protected:
bool init() {
initGLProgramState("example_greyScale.fsh");
return true;
}
};
//
// Effect参考官方实例
//
bool Effect::initGLProgramState(const std::string &fragmentFilename)
{
auto fileUtiles = FileUtils::getInstance();
auto fragmentFullPath = fileUtiles->fullPathForFilename(fragmentFilename);
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
_fragSource = fragSource;
#endif
_glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
_glprogramstate->retain();
return _glprogramstate != nullptr;
}
Effect::Effect()
: _glprogramstate(nullptr)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
_backgroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED,
[this](EventCustom*)
{
auto glProgram = _glprogramstate->getGLProgram();
glProgram->reset();
glProgram->initWithByteArrays(ccPositionTextureColor_noMVP_vert, _fragSource.c_str());
glProgram->link();
glProgram->updateUniforms();
}
);
Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backgroundListener, -1);
#endif
}
Effect::~Effect()
{
CC_SAFE_RELEASE_NULL(_glprogramstate);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
Director::getInstance()->getEventDispatcher()->removeEventListener(_backgroundListener);
#endif
}
3、example_greyScale.fsh(颜色定义)
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
void main(void)
{
vec4 c = texture2D(CC_Texture0, v_texCoord);
gl_FragColor.xyz = vec3(0.2126*c.r + 0.7152*c.g + 0.0722*c.b);
gl_FragColor.w = c.w;
}
4、使用代码:
EffectSprite* _sprite = EffectSprite::create("blueSprite.png");
_sprite->setPosition(Vec2(200, visibleSize.height / 2));
addChild(_sprite);