shader代码
#ifdef GL_ES
precision lowp float;
#endif
uniform sampler2D u_texture;
uniform sampler2D u_mask;
uniform float factor;
uniform float width;
uniform float offset;
uniform vec3 color;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
const float SQRT_2 = 1.414f;
void main()
{
vec4 texColor = texture2D(u_texture, v_texCoord);
float distance = abs(v_texCoord[0]+v_texCoord[1]-offset)/SQRT_2;
distance = 1.0f-(1.0f/width)*distance;
distance = max(distance, 0.0f);
vec4 sample = vec4(0.0f,0.0f,0.0f,0.0f);
sample.rgb = color * distance;
sample.a = distance;
float alpha = sample[3]*texColor[3];
texColor[0] = texColor[0] + sample[0]*alpha*factor;
texColor[1] = texColor[1] + sample[1]*alpha*factor;
texColor[2] = texColor[2] + sample[2]*alpha*factor;
gl_FragColor = v_fragmentColor * texColor;
}
cocos2d-x中的代码
#pragma once
#pragma ececution_character_set("utf-8")
#include
#include "cocos2d.h"
#include "ui/CocosGUI.h"
class ShaderNode : public cocos2d::Node
{
public:
CREATE_FUNC(ShaderNode);
static ShaderNode* shaderNodeWithVertex(const std::string &vert, const std::string &frag);
virtual void update(float dt) override;
virtual void setPosition(const cocos2d::Vec2 &newPosition) override;
virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) override;
protected:
ShaderNode();
~ShaderNode();
bool initWithVertex(const std::string &vert, const std::string &frag);
void loadShaderVertex(const std::string &vert, const std::string &frag);
void onDraw(const cocos2d::Mat4& transform, uint32_t flags);
cocos2d::Vec2 _center;
cocos2d::Vec2 _resolution;
cocos2d::Vec3 _color;
float _factor;
float _windth;
float _offset;
float _time;
cocos2d::Sprite * _sprite;
std::string _vertFileName;
std::string _fragFileName;
cocos2d::CustomCommand _customCommand;
};
#include "ShaderNode.h"
USING_NS_CC;
enum
{
SIZE_X = 256,
SIZE_Y = 256,
};
ShaderNode::ShaderNode()
:_time(0.0f)
, _factor(1.0f)
, _windth(0.3f)
, _offset(2.0f)
, _color(Vec3(0.4f,0.4f,0.4f))
{
}
ShaderNode::~ShaderNode()
{
}
ShaderNode* ShaderNode::shaderNodeWithVertex(const std::string &vert, const std::string& frag)
{
auto node = new (std::nothrow) ShaderNode();
node->initWithVertex(vert, frag);
node->autorelease();
return node;
}
bool ShaderNode::initWithVertex(const std::string &vert, const std::string &frag)
{
_vertFileName = vert;
_fragFileName = frag;
#if CC_ENABLE_CACHE_TEXTURE_DATA
auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event){
this->setGLProgramState(nullptr);
loadShaderVertex(_vertFileName, _fragFileName);
});
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
#endif
loadShaderVertex(vert, frag);
_time = 0;
_resolution = Vec2(SIZE_X, SIZE_Y);
scheduleUpdate();
setContentSize(Size(SIZE_X, SIZE_Y));
setAnchorPoint(Vec2(0.5f, 0.5f));
return true;
}
void ShaderNode::loadShaderVertex(const std::string &vert, const std::string &frag)
{
auto fileUtiles = FileUtils::getInstance();
auto fragmentFilePath = fileUtiles->fullPathForFilename(frag);
auto fragSource = fileUtiles->getStringFromFile(fragmentFilePath);
std::string vertSource;
if (vert.empty()) {
vertSource = ccPositionTextureColor_vert;
}
else {
std::string vertexFilePath = fileUtiles->fullPathForFilename(vert);
vertSource = fileUtiles->getStringFromFile(vertexFilePath);
}
auto sp = Sprite::create("PushCard1.png");
_sprite = Sprite::createWithTexture(sp->getTexture());
auto glprogram = GLProgram::createWithByteArrays(vertSource.c_str(), fragSource.c_str());
auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
_sprite->setGLProgramState(glprogramstate);
addChild(_sprite);
}
void ShaderNode::update(float dt)
{
if (_factor > 4.0f)
{
_factor = 1.4f;
}
_offset = _offset - dt;
if (_offset < 0.0f)
{
_offset = 3.0f;
}
}
void ShaderNode::setPosition(const Vec2 &newPosition)
{
Node::setPosition(newPosition);
auto position = getPosition();
auto frameSize = Director::getInstance()->getOpenGLView()->getFrameSize();
auto visibleSize = Director::getInstance()->getVisibleSize();
auto retinaFactor = Director::getInstance()->getOpenGLView()->getRetinaFactor();
_center = Vec2(position.x * frameSize.width / visibleSize.width * retinaFactor, position.y * frameSize.height / visibleSize.height * retinaFactor);
}
void ShaderNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
_customCommand.init(_globalZOrder, transform, flags);
_customCommand.func = CC_CALLBACK_0(ShaderNode::onDraw, this, transform, flags);
renderer->addCommand(&_customCommand);
}
void ShaderNode::onDraw(const Mat4 &transform, uint32_t flags)
{
auto glProgramState = _sprite->getGLProgramState();
glProgramState->setUniformFloat("factor", _factor);
glProgramState->setUniformFloat("width", _windth);
glProgramState->setUniformFloat("offset", _offset);
glProgramState->setUniformVec3("color", _color);
glProgramState->setUniformTexture("u_texture", _sprite->getTexture());
}
ShaderNode用法
auto sn = ShaderNode::shaderNodeWithVertex("", "efx_stream.fsh");
auto s = Director::getInstance()->getWinSize();
sn->setPosition(Vec2(s.width / 2, s.height / 2));
addChild(sn);