Shader lag after some time

@All Community and @stevetranby @dotsquid

I have a very basic shader setup, it run perfectly but after some time it seems to be lagged by gpu. I have no idea what is causing this issue, can any one pls take a look at it.
here is My shader setup

void ShaderSprite::setShaders(std::string fileName){
 this->getTexture()->setAntiAliasTexParameters();
 if(fileName=="")return;
 GLchar * fragmentSource = (GLchar*) String::createWithContentsOfFile(                  FileUtils::getInstance()->fullPathForFilename( fileName.c_str()).c_str() )->getCString();
// Create a GLProgram with the shader file.
auto p = GLProgram::createWithByteArrays( ccPositionTextureColor_noMVP_vert, fragmentSource );
// Create a GLProgramState from the GLProgram.
auto glProgramState = GLProgramState::getOrCreateWithGLProgram( p );
this->setGLProgramState( glProgramState );
}

ShaderSprite is a Custom class which extends Sprite. And here is my shader.fsh file

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
const float speed = 4.0;
const float bendFactor = 0.1;
void main()
{ 
float height =   1.0 - v_texCoord.y;
float offset = pow(height, 2.5);

 // 4 multiply by sin since it gives us nice bending
offset *= (sin(CC_Time[1] * speed) * bendFactor);

vec4 normalColor = texture2D(CC_Texture0, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgba;
gl_FragColor = vec4(normalColor);
}

and this is how i use this shader

ShaderSprite *grass2 = ShaderSprite::createSprite("grass2.png", "shader.fsh");
grass2->setScale(2);
grass2->setPosition(Vec2(visibleSize.width/2,visibleSize.height/2));
this->addChild(grass2,8);

I don’t know if this fits your case, but I made the experience that trigonometric functions in shaders can’t handle big values very well.
One way to fix it could be to change renderer/CCGLProgram.cpp, line 928 (in cocos2d-x-3.6) from

setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_TIME], time/10.0, time, time*2, time*4);

to

setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_TIME], fmodf(time*4.0f, 2.0f*M_PI), time, time*2, time*4);

and changing your shader.fsh sin function line to

offset *= (sin(CC_Time[0]) * bendFactor);

But only of course if you don’t use CC_Time[0] somewhere else…

Maybe you don’t even want to use sin() in your fragment shader and let the CPU handle it in CCGLProgram.cpp. For example with CC_SinTime[0] (that would be on line below in CCGLProgram.cpp: line 929:

setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_SIN_TIME], sinf(time*4.0), time/4.0, time/2.0, sinf(time));

And in your shader.fsh:

offset *= CC_SinTime[0] * bendFactor;

Again: only do this, if you don’t use CC_SinTime[0] somewhere else…

Thanx for the info, i will check that(i am bit occupied in something else) and try to change my shader accordingly and report back, what i was thinking is passing offset value as a uniform, and calculate it in update, any thoughts about that. I am not sure about changing CC_Time[] , as i am unsure if CC_Time[] is being used internally by engine itself somewhere else.

As far as I know, CC_Time isn’t used in any of the default shaders. I changed it in one of my projects and didn’t have any problems.
But you could of course use your own uniform just to be one the safe side.

Calculating offset in update won’t work, because it depends on v_texCoord which is different for every fragment. But you should definitely take speed and bendFactor out of the shader since they are constant for every fragment.
Pass a uniform called offsetMultiplier or something similar… (= sinf(time * speed) * bendFactor)

I think i will go with offsetMultiplier approcah, as i can manage my shader behaviour whenever i want it to, i’ll share an update when i am done. Thanx for you time

i did scrap constants and sine calculations from shader and passed them as uniforms. Interestingly sinf(time * speed) * bendFactor) gives a funny curve, something i didn’t anticipated but fits perfectly in my use case, it gives a more natural feeling. Thanx

Strange. But great it worked out for you.