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.414 f;
void main()
{
vec4 texColor = texture2D (u_texture, v_texCoord);
float distance = abs (v_texCoord[0 ]+v_texCoord[1 ]-offset)/SQRT_2;
distance = 1.0 f-(1.0 f/width)*distance ;
distance = max (distance , 0.0 f);
vec4 sample = vec4 (0.0 f,0.0 f,0.0 f,0.0 f);
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 <iostream>
#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);