The two things Iâd point out is you should only have to change the spriteâs position and the beam should move around (the generated texture from the shader shouldnât change with spriteâs position, unless youâre modifying the standard vertex gl_Position assignment).
I canât help make the shader perfect without spending more time and knowing what output you actually want, but hereâs a test that seems to work as you want.
This might be the similar to the final code you ended up writing, but you can just change the position of the sprite as normal and the shader will display as expected. This specific shader has an iResolution
variable that is unique to this shader and is only relevant to this specific shader, or some set of shadertoy shaders.
ShaderToy examples can usually be ported over successfully, but you do have to remember those are shaders essentially using a full resolution of a frame buffer, specifically for âfull screenâ demos.
Any excess/verbose code is due to how I test or reformat code for the forum.
using std::string;
// custom shader similar to alpha test, but with normals and lighting
string kShaderKey("laser_rainbow");
auto glCache = GLProgramCache::getInstance();
auto prog = glCache->getGLProgram(kShaderKey.c_str());
if(! prog)
{
prog = GLProgram::createWithFilenames("res/" + kShaderKey + ".vert",
"res/" + kShaderKey + ".frag");
glCache->addGLProgram(prog, kShaderKey);
}
// This is the display size of the quad where for the render beam in pixels
// you should be able to make this any size you want and get
// a longer/short/wider beam
Size texSize(400,80);
// empty white quad with 2x2 pixel texture
auto sprite = Sprite::create();
sprite->setPosition(Vec2(250,150));
// you should be able to anchor anywhere,
sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
// expand the quad vertices to cover this rect
// since the uv coords, including wrapping, are specific this cannot
// be changed without affecting display
sprite->setTextureRect(Rect(0, 0, texSize.width, texSize.height));
// looked better with additive :)
sprite->setBlendFunc(BlendFunc::ADDITIVE);
//auto glprogram = GLProgram::createWithFilenames("water.vsh", "water.fsh");
auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(prog);
sprite->setGLProgramState(glprogramstate);
// note: iResolution is only "size of screen" because shadertoy applys to full view quad
// apparently the shader prefers getting this iResolution at half size in my testing
auto scale_factor = Director::getInstance()->getContentScaleFactor();
Vec3 iResolution(texSize.width/(2.f / scale_factor),
texSize.height/(2.f / scale_factor),
scale_factor);
glprogramstate->setUniformVec3("iResolution", );
// quick movement test to confirm
auto move = MoveBy::create(5.0f, Vec2(100,100));
auto seq = Sequence::create(move, move->reverse(), NULL);
sprite->runAction(RepeatForever::create(seq));
parent->addChild(testSprite);
This may still not be the result you want, but it seems to work for me ??
Edit: the shader was mostly ported verbatim.
//vert
varying float iGlobalTime;
// inside main (you can test the other 0-3 array index)
iGlobalTime = CC_Time[1];
// frag
uniform vec3 iResolution;
varying float iGlobalTime;