Why fragment shaders cannot work in Cocos2d-x?

I want to use OpenGL shaders ,but these codes cannot work, Who can help me? Thank you very much.

#include "CSEGrass.h"
CSEGrass *CSEGrass::create()
{
    CSEGrass *ret = new CSEGrass();
    if (ret && ret->init())
    {
        ret->autorelease();
        return ret;
    }
    else
    {
        CC_SAFE_DELETE(ret);
        return nullptr;
    }
}

bool CSEGrass::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    _sprite = Sprite::create("grass.png");
    _sprite->setAnchorPoint(Point::ZERO);
    _sprite->setPosition(Point::ZERO);
    this->addChild(_sprite);
    
    GLchar* fragmentSource = (GLchar*)"\n\
    #ifdef GL_ES \n\
    precision mediump float; \n\
    #endif \n\
    varying vec2 v_texCoord; \n\
    uniform sampler2D u_texture; \n\
    uniform float u_time; \n\
    const float speed = 2.0; \n\
    const float bendFactor = 0.2; \n\
    void main() { \n\
    float height = 1.0 - v_texCoord.y; \n\
    float offset = pow(height, 2.5); \n\
    offset *= (sin(u_time * speed) * bendFactor); \n\
    vec3 normalColor = texture2D(u_texture, fract(vec2(v_texCoord.x + offset, v_texCoord.y))).rgb; \n\
    gl_FragColor = vec4(normalColor, 1); \n\
    }";
    
    GLProgram* pProgram = new GLProgram();
    pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, fragmentSource);
    _sprite->setShaderProgram(pProgram);
    pProgram->release();
    
    CHECK_GL_ERROR_DEBUG();
    
    _sprite->getShaderProgram()->addAttribute(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
    _sprite->getShaderProgram()->addAttribute(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR);
    _sprite->getShaderProgram()->addAttribute(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS);
    
    CHECK_GL_ERROR_DEBUG();
    
    _sprite->getShaderProgram()->link();
    
    CHECK_GL_ERROR_DEBUG();
    
    _sprite->getShaderProgram()->updateUniforms();
    
    CHECK_GL_ERROR_DEBUG();
    
    _timeUniformLocation = glGetUniformLocation( _sprite->getShaderProgram()->getProgram(), "u_time");
    
    this->scheduleUpdate();
    
    _sprite->getShaderProgram()->use();
    
    return true;
}

void CSEGrass::update(float delta) {
    _totalTime += delta;
    _sprite->getShaderProgram()->use();
    glUniform1f(_timeUniformLocation, _totalTime);
}

do you have any log output?

Don’t you need to implement a custom command function?