The shaders that are part of Cocos2d-x v4 should be plentiful to learn from, but if you want to know how to convert between an implementation you may see online to what cocos2d-x requires, then the following may help you.
Check out this shader implementation on Shadertoy: https://www.shadertoy.com/view/XsVSDz
In one of the comments that page, you’ll see a simplified implementation, like this:
void mainImage( out vec4 O, vec2 U )
{
float t = iTime/.1 + iMouse.x;
vec2 R = iResolution.xy, S = vec2(160,100),
p = ( U+U - R ) / R * S,
q = vec2(cos(-t / 165.), cos( t / 45.)) * S - p;
t = 1. + cos( length( vec2(cos( t / 98.), sin( t / 178.)) * S - p ) / 30.)
+ cos( length( vec2(sin(-t / 124.), cos( t / 104.)) * S - p ) / 20.)
+ sin( length(q) / 25. ) * sin(q.x / 20.) * sin(q.y / 15.);
O = .5 + .5* cos( (iTime+iMouse.y) / vec4(63,78,45,1) + ( t + vec4(0,1,-.5,0) ) *3.14 );
}
Now, the reason I’m posting this up is because it may help you learn how to convert one of those to Cocos2d-x, although in my particular case I’ve converted it to Axmol, which is a fork of Cocos2d-x v4, and it does work:
const std::string shader_plasma_frag =
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"varying vec4 v_fragmentColor;\n"
"varying vec2 v_texCoord;\n"
"\n"
"uniform float u_time; // time in seconds\n"
"uniform vec2 u_resolution;\n"
"uniform vec2 u_position;\n"
"\n"
"const float MATH_PI = float(3.14159265359);\n"
"\n"
"void main()\n"
"{\n"
" float t = u_time / .1 + u_position.x;\n"
" vec2 R = u_resolution.xy, S = vec2(160, 100),\n"
" p = (v_texCoord + v_texCoord - R) / R * S,\n"
" q = vec2(cos(-t / 165.), cos(t / 45.)) * S - p;\n"
" t = 1. + cos(length(vec2(cos(t / 98.), sin(t / 178.)) * S - p) / 30.)\n"
" + cos(length(vec2(sin(-t / 124.), cos(t / 104.)) * S - p) / 20.)\n"
" + sin(length(q) / 25.) * sin(q.x / 20.) * sin(q.y / 15.);\n"
" gl_FragColor = .5 + .5 * cos((u_time + u_position.y) / vec4(63, 78, 45, 1) + (t + vec4(0, 1, -.5, 0)) * MATH_PI);\n"
"}\n";
// In TestScene.cpp
void TestScene::PlasmaTest()
{
const auto visibleSize = Director::getInstance()->getVisibleSize();
auto* program = backend::Device::getInstance()->newProgram(positionTextureColor_vert, shader_plasma_frag);
_plasmaProgramState = new ProgramState(program);
// NOTE THAT PROGRAM AND PROGRAMSTATE ARE NOT AUTORELEASED!
CC_SAFE_RELEASE_NULL(program); // Must release it here
auto* rt = RenderTexture::create(1, 1);
rt->clear(255, 255, 255, 255);
auto* node = Sprite::createWithTexture(rt->getSprite()->getTexture());
node->setContentSize(visibleSize);
node->setStretchEnabled(true);
node->setPositionNormalized(Vec2(0.5f, 0.5f));
addChild(node, 1);
node->setProgramState(_plasmaProgramState);
auto* touchListener = EventListenerTouchOneByOne::create();
touchListener->setSwallowTouches(false);
touchListener->onTouchBegan = [this, node](Touch* t, Event*) -> bool {
auto loc = t->getLocation();
loc = node->convertToNodeSpace(loc);
_plasmaProgramState->setUniform(_plasmaPosLoc, &loc, sizeof(loc));
return true;
};
touchListener->onTouchMoved = [this, node](Touch* t, Event*) {
auto loc = t->getLocation();
loc = node->convertToNodeSpace(loc);
_plasmaProgramState->setUniform(_plasmaPosLoc, &loc, sizeof(loc));
};
touchListener->onTouchEnded = [this, node](Touch* t, Event*) {
auto loc = t->getLocation();
loc = node->convertToNodeSpace(loc);
_plasmaProgramState->setUniform(_plasmaPosLoc, &loc, sizeof(loc));
};
getEventDispatcher()->addEventListenerWithSceneGraphPriority(touchListener, node);
_plasmaTimeLoc = _plasmaProgramState->getUniformLocation("u_time");
_plasmaResolutionLoc = _plasmaProgramState->getUniformLocation("u_resolution");
_plasmaPosLoc = _plasmaProgramState->getUniformLocation("u_position");
auto time = 0.f;
_plasmaProgramState->setUniform(_plasmaTimeLoc, &time, sizeof(time));
auto resolution = Vec2(node->getContentSize()) / node->getContentSize().width;
_plasmaProgramState->setUniform(_plasmaResolutionLoc, &resolution, sizeof(resolution));
auto position = Vec2(node->getContentSize()) / 2;
_plasmaProgramState->setUniform(_plasmaPosLoc, &position, sizeof(position));
}
// In TestScene.h:
cocos2d::backend::ProgramState* _plasmaProgramState = nullptr;
cocos2d::backend::UniformLocation _plasmaPosLoc;
cocos2d::backend::UniformLocation _plasmaTimeLoc;
cocos2d::backend::UniformLocation _plasmaResolutionLoc;
It should work exactly the same way as the Shadertoy implementation, so if you click anywhere on the screen, it’ll change colors etc…
If you try this and get compilation errors, then you’ll need to sort them out yourself, because as I mentioned earlier, this is working on the Axmol fork of Cocos2d-x v4, so there may be slight differences.