这个例子做得就比较顺了,基本没遇到什么坎。
顶点着色器:
attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif
void main()
{
gl_Position = CC_PMatrix * a_position;
v_fragmentColor = a_color;
v_texCoord = a_texCoord;
}
片段着色器:
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
uniform float u_alpha;
uniform vec4 u_blendColor;
void main(void)
{
vec4 realColor = texture2D(CC_Texture0, v_texCoord);
if (realColor.a > 0.)
{
gl_FragColor = u_blendColor * u_alpha + realColor * (1. - u_alpha);
}
else
{
discard;
}
}
BlendAction.h
class BlendAction : public ActionInterval
{
public:
static BlendAction* create(float flDuring, Color4B blendColor, bool bReverse = false);
virtual BlendAction* reverse() const override;
private:
bool _reverse = false;
Color4B _color;
GLProgramState* _pstate = nullptr;
float _percent = 0.0f;
bool initWithParas(float flDuring, Color4B blendColor, bool bReverse);
virtual void startWithTarget(Node *target) override;
virtual void update(float t) override;
virtual void stop(void) override;
};
BlendAction.cpp
#include "BlendAction.hpp"
// 书中省略的地方
BlendAction* BlendAction::create(float flDuring, Color4B blendColor, bool bReverse)
{
BlendAction *ret = new (std::nothrow) BlendAction();
if (ret && ret->initWithParas(flDuring, blendColor, bReverse))
{
ret->autorelease();
return ret;
}
delete ret;
return nullptr;
}
// 书中省略的地方
bool BlendAction::initWithParas(float flDuring, Color4B blendColor, bool bReverse)
{
if (initWithDuration(flDuring) == false)
{
return false;
}
_color = blendColor;
_reverse = bReverse;
return true;
}
void BlendAction::startWithTarget(Node *target)
{
ActionInterval::startWithTarget(target);
_pstate = target->getGLProgramState();
_pstate->retain();
auto program = GLProgram::createWithFilenames("res/ccShader_PositionTextureColor_noMVP.vert", "res/blend_color.frag");
auto pstate = GLProgramState::create(program);
target->setGLProgramState(pstate);
pstate->setUniformCallback("u_alpha", [this](GLProgram* p, Uniform* u)
{
p->setUniformLocationWith1f(u->location, _percent);
});
auto blendColor = Vec4(_color.r / 255.0, _color.g / 255.0, _color.b / 255.0, _color.a / 255.0);
pstate->setUniformVec4("u_blendColor", blendColor);
}
void BlendAction::update(float t)
{
_percent = _reverse ? 1.0 - t : t;
}
void BlendAction::stop(void)
{
getTarget()->setGLProgramState(_pstate);
_pstate->autorelease();
}
// 书中省略的地方
BlendAction* BlendAction::reverse() const
{
return BlendAction::create(_duration, _color, true);
}
在HelloWorldScene.cpp中使用
bool HelloWorld::init()
{
... ... // 略掉的原有内容
auto sprite = Sprite::create("HelloWorld.png");
sprite->setPosition(_center);
addChild(sprite, 10);
auto bColor = BlendAction::create(10, Color4B::RED);
auto rColor = bColor->reverse();
auto sequence = Sequence::create(bColor, rColor, NULL);
sprite->runAction(Repeat::create(sequence, 100));
return true;
}
最终效果: