effectSprite

头文件

#ifndef __EFFECT_SPRITE_H__
#define __EFFECT_SPRITE_H__

#include "cocos2d.h"
USING_NS_CC;




class EffectSprite;
class Effect : public Ref
{
public:
	GLProgramState* getGLProgramState() const { return _glprogramstate; }
	virtual void setTarget(EffectSprite *sprite){}

protected:
	bool 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()
		: _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
	}
	virtual ~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
	}
	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
};



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) {
		if (_defaultEffect != effect) {
			effect->setTarget(this);

			CC_SAFE_RELEASE(_defaultEffect);
			_defaultEffect = effect;
			CC_SAFE_RETAIN(_defaultEffect);

			setGLProgramState(_defaultEffect->getGLProgramState());
		}
	}
	/*void addEffect(Effect *effect, ssize_t order) {
		effect->retain();
		effect->setTarget(this);

		_effects.push_back(std::make_tuple(order, effect, QuadCommand()));

		std::sort(std::begin(_effects), std::end(_effects), tuple_sort);
	}*/

	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
		{
			// negative effects: order < 0
			int idx = 0;
			for (auto &effect : _effects) {

				if (std::get<0>(effect) >= 0)
					break;
				QuadCommand &q = std::get<2>(effect);
				q.init(_globalZOrder, _texture->getName(), std::get<1>(effect)->getGLProgramState(), _blendFunc, &_quad, 1, transform/*, flags*/);
				renderer->addCommand(&q);
				idx++;

			}

			// normal effect: order == 0
			_quadCommand.init(_globalZOrder, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, transform/*, flags*/);
			renderer->addCommand(&_quadCommand);

			// postive effects: oder >= 0
			for (auto it = std::begin(_effects) + idx; it != std::end(_effects); ++it) {
				QuadCommand &q = std::get<2>(*it);
				q.init(_globalZOrder, _texture->getName(), std::get<1>(*it)->getGLProgramState(), _blendFunc, &_quad, 1, transform/*, flags*/);
				renderer->addCommand(&q);
				idx++;
			}
		}
	}
protected:
	EffectSprite() : _defaultEffect(nullptr)
	{
		_effects.reserve(2);
	}
	~EffectSprite() {
		for (auto &tuple : _effects) {
			std::get<1>(tuple)->release();
		}
		CC_SAFE_RELEASE(_defaultEffect);
	}

	std::vector<std::tuple<ssize_t, Effect*, QuadCommand>> _effects;
	Effect* _defaultEffect;
};


// Outline
class EffectOutline : public Effect
{
public:
	CREATE_FUNC(EffectOutline);

	bool init()
	{
		initGLProgramState("Shaders/example_outline.fsh");

		Vec3 color(1.0f, 0.2f, 0.3f);
		GLfloat radius = 0.01f;
		GLfloat threshold = 1.75;

		_glprogramstate->setUniformVec3("u_outlineColor", color);
		_glprogramstate->setUniformFloat("u_radius", radius);
		_glprogramstate->setUniformFloat("u_threshold", threshold);
		return true;
	}
};

// Noise
class EffectNoise : public Effect
{
public:
	CREATE_FUNC(EffectNoise);

protected:
	bool init() {
		initGLProgramState("Shaders/example_Noisy.fsh");
		return true;
	}

	virtual void setTarget(EffectSprite* sprite) override
	{
		auto s = sprite->getTexture()->getContentSizeInPixels();
		getGLProgramState()->setUniformVec2("resolution", Vec2(s.width, s.height));
	}
};

// Edge Detect
class EffectEdgeDetect : public Effect
{
public:
	CREATE_FUNC(EffectEdgeDetect);

protected:
	bool init() {
		initGLProgramState("Shaders/example_edgeDetection.fsh");
		return true;
	}

	virtual void setTarget(EffectSprite* sprite) override
	{
		auto s = sprite->getTexture()->getContentSizeInPixels();
		getGLProgramState()->setUniformVec2("resolution", Vec2(s.width, s.height));
	}
};

// Grey
class EffectGreyScale : public Effect
{
public:
	CREATE_FUNC(EffectGreyScale);

protected:
	bool init() {
		initGLProgramState("Shaders/example_greyScale.fsh");
		return true;
	}
};

// Sepia
class EffectSepia : public Effect
{
public:
	CREATE_FUNC(EffectSepia);

protected:
	bool init() {
		initGLProgramState("Shaders/example_sepia.fsh");
		return true;
	}
};

// bloom
class EffectBloom : public Effect
{
public:
	CREATE_FUNC(EffectBloom);

protected:
	bool init() {
		initGLProgramState("Shaders/example_bloom.fsh");
		return true;
	}

	virtual void setTarget(EffectSprite* sprite) override
	{
		auto s = sprite->getTexture()->getContentSizeInPixels();
		getGLProgramState()->setUniformVec2("resolution", Vec2(s.width, s.height));
	}
};

// cel shading
class EffectCelShading : public Effect
{
public:
	CREATE_FUNC(EffectCelShading);

protected:
	bool init() {
		initGLProgramState("Shaders/example_celShading.fsh");
		return true;
	}

	virtual void setTarget(EffectSprite* sprite) override
	{
		auto s = sprite->getTexture()->getContentSizeInPixels();
		getGLProgramState()->setUniformVec2("resolution", Vec2(s.width, s.height));
	}
};

// Lens Flare
class EffectLensFlare : public Effect
{
public:
	CREATE_FUNC(EffectLensFlare);

protected:
	bool init() {
		initGLProgramState("Shaders/example_lensFlare.fsh");
		return true;
	}

	virtual void setTarget(EffectSprite* sprite) override
	{
		auto s = sprite->getTexture()->getContentSizeInPixels();
		getGLProgramState()->setUniformVec2("textureResolution", Vec2(s.width, s.height));

		s = Director::getInstance()->getWinSize();
		getGLProgramState()->setUniformVec2("resolution", Vec2(s.width, s.height));

	}
};

class EffectNormalMapped : public Effect
{
public:
	CREATE_FUNC(EffectNormalMapped);
	static EffectNormalMapped* create(const std::string&normalMapFileName)
	{
		EffectNormalMapped *normalMappedSprite = new (std::nothrow) EffectNormalMapped();
		if (normalMappedSprite && normalMappedSprite->init() && normalMappedSprite->initNormalMap(normalMapFileName))
		{

			normalMappedSprite->autorelease();
			return normalMappedSprite;
		}
		CC_SAFE_DELETE(normalMappedSprite);
		return nullptr;
	}
	void setKBump(float value);
	void setLightPos(const Vec3& pos);
	void setLightColor(const Color4F& color);
	float getKBump()const{ return _kBump; }
protected:
	bool init();
	bool initNormalMap(const std::string&normalMapFileName);
	virtual void setTarget(EffectSprite* sprite) override;
	EffectSprite* _sprite;
	Vec3 _lightPos;
	Color4F _lightColor;
	float  _kBump;
};

bool EffectNormalMapped::init()
{
	initGLProgramState("Shaders3D/Normal.frag");
	_kBump = 2;
	return true;
}
bool EffectNormalMapped::initNormalMap(const std::string& normalMapFileName)
{
	auto normalMapTextrue = Director::getInstance()->getTextureCache()->addImage(normalMapFileName);
	getGLProgramState()->setUniformTexture("u_normalMap", normalMapTextrue);
	return true;
}
void EffectNormalMapped::setTarget(EffectSprite* sprite)
{
	_sprite = sprite;
	getGLProgramState()->setUniformFloat("u_kBump", _kBump);
	getGLProgramState()->setUniformVec2("u_contentSize", Vec2(sprite->getContentSize().width, sprite->getContentSize().height));
}

void EffectNormalMapped::setKBump(float value)
{
	_kBump = value;
	auto glProgramState = getGLProgramState();
	if (glProgramState) glProgramState->setUniformFloat("u_kBump", _kBump);
}

void EffectNormalMapped::setLightPos(const Vec3& pos)
{
	_lightPos = pos;
	auto glProgramState = getGLProgramState();
	if (glProgramState) glProgramState->setUniformVec4("u_lightPosInLocalSpace", Vec4(_lightPos.x, _lightPos.y, _lightPos.z, 1));

}

void EffectNormalMapped::setLightColor(const Color4F& color)
{
	_lightColor = color;
	auto glProgramState = getGLProgramState();
	if (glProgramState) getGLProgramState()->setUniformVec3("u_diffuseL", Vec3(_lightColor.r, _lightColor.g, _lightColor.b));

}

#endif //__EFFECT_SPRITE_H__

用法

auto _sprite = EffectSprite::create("HelloWorld.png");
	_sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
	addChild(_sprite);
	_sprite->setEffect(EffectGreyScale::create());





你可能感兴趣的:(effectSprite)