Made a toony water shader (Super fast) V3.2+

Code:

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    auto sp = Sprite::create("water.png", Rect(0,0, visibleSize.width, visibleSize.height));
    addChild(sp);
    sp->setPosition(Point(visibleSize/2));
    
    auto TexCache = Director::getInstance()->getTextureCache();
    auto wave2 = TexCache->addImage("wave1.png");
    auto wave1 = TexCache->addImage("18.jpg");
    wave1->setTexParameters(Texture2D::TexParams{GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT});
    wave2->setTexParameters(Texture2D::TexParams{GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT});
    auto glprogram = GLProgram::createWithFilenames("water.vsh", "water.fsh");
    auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
    sp->setGLProgramState(glprogramstate);
    
    glprogramstate->setUniformTexture("u_wave1", wave1);
    glprogramstate->setUniformTexture("u_wave2", wave2);
    glprogramstate->setUniformFloat("saturateValue", 1.2);

    sp->setRotation3D(Vec3(-60,0,0));
    return true;
}

Frag Shader:


#ifdef GL_ES
precision mediump float;
#endif

varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform sampler2D u_wave1;
uniform sampler2D u_wave2;
uniform float u_interpolate;
uniform float saturateValue;
float verticalSpeed = 0.3797;
float horizontalSpeed = 0.77;
void main() {
    vec2 textCoord1 = v_texCoord;
    textCoord1.x += verticalSpeed * CC_Time.x;
    textCoord1.x = fract(textCoord1.x);
    textCoord1.y += horizontalSpeed * CC_Time.x;
    textCoord1.y = fract(textCoord1.y);
    vec3 color = texture2D(u_wave1, textCoord1).xyz;
    color += texture2D(u_wave2, v_texCoord).xyz;
    if(color.x > saturateValue)
        color = vec3(1.0);
    else
        color = texture2D(CC_Texture0, v_texCoord).xyz;
    gl_FragColor = vec4(color, 1.0);
}

images

Now give me some hearts :smiley:

17 Likes

i think this post should become a tutorial or example

Thank you for sharing, It’s very interesting.
Where to put the 2’nd block of code for Frag Shader.

make a new file like “water.fsh”, for vertex shader, just use the standard one

What about “water.vsh”

auto glprogram = GLProgram::createWithFilenames(“water.vsh”, “water.fsh”);


attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

#ifdef GL_ES
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
#else
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;
#endif

void main()
{
    gl_Position = CC_PMatrix * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}

@Wuhao Thanks a lot this was very helpful.

This looks really awesome. I’d like to try it out myself but I can’t seem to add this to my project.
When I run the application it breaks. I added the vsh and fsh files to the resources but it seems that the code is incorrect. Has someone run it actually here?

How to create the two file “water.vsh” and “water.fsh” have any tool or just copy the code above, have any change for different effect?
Where to put it when i have different resources for multiple resolution application.

I put images file water.png, wave1.png, 18.jpg and two file water.fsh, water.vsh to Resources folder, I try the code to make the shader as your code

auto sp = Sprite::create(“water.png”, Rect(0, 0, visibleSize.width, visibleSize.height));
sp->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
this->addChild(sp);

auto TexCache = Director::getInstance()->getTextureCache();
auto wave2 = TexCache->addImage("wave1.png");
auto wave1 = TexCache->addImage("18.jpg");
Texture2D::TexParams tp = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };

wave1->setTexParameters(tp);
wave2->setTexParameters(tp);

auto glprogram = GLProgram::createWithFilenames("water.vsh", "water.fsh");
auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
sp->setGLProgramState(glprogramstate);

glprogramstate->setUniformTexture("u_wave1", wave1);
glprogramstate->setUniformTexture("u_wave2", wave2);
glprogramstate->setUniformFloat("saturateValue", 1.2);

sp->setRotation3D(Vec3(-60, 0, 0));

and the game crash when run to the line

wave1->setTexParameters(tp);

The two line of code below, got syntax error C2143: syntax error : missing ‘)’ before ‘{’ when compile

wave1->setTexParameters(Texture2D::TexParams{GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT});
wave2->setTexParameters(Texture2D::TexParams{GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT});

So I replace by the three line of code as below

Texture2D::TexParams tp = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT };
wave1->setTexParameters(tp);
wave2->setTexParameters(tp);

How to solve this problem?

I want to have a example with v2 (v2.2.5). Please help me ??!!!

I change the TexParams from GL_REPEAT to GL_CLAMP_TO_EDGE

Below is my code

auto sp = Sprite::create("water.png", Rect(0, 0, visibleSize.width, visibleSize.height));
    sp->setPosition(Vec2(visibleSize.width / 2, visibleSize.height / 2));
    this->addChild(sp);
    
    Texture2D *wave2 = TextureCache::sharedTextureCache()->addImage("wave1.png");
    Texture2D *wave1 = TextureCache::sharedTextureCache()->addImage("18.jpg");
    
    Texture2D::TexParams tp = { GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
    
    wave1->setTexParameters(tp);
    wave2->setTexParameters(tp);
    
    auto glprogram = GLProgram::createWithFilenames("water.vsh", "water.fsh");
    auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);
    sp->setGLProgramState(glprogramstate);
    
    glprogramstate->setUniformTexture("u_wave1", wave1);
    glprogramstate->setUniformTexture("u_wave2", wave2);
    glprogramstate->setUniformFloat("saturateValue", 1.2);
    
    sp->setRotation3D(Vec3(-60, 0, 0));

When the program run to the line

auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);

it cause crash, i don’t know what happen? May be the water.fsh and water.vsh not correct.

The image water.png, wave1.png, 18.jpg have size is 512x512 it mean pow of 2.

Can any body help me?

it’s so awsome,

Hi, you can run the code without error? I am testing on the windows phone 8.1 (Nokia Lumia 630).
When run to the line

 auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram);

The application crashed, My laptop is old so i can’t debug, I just can test on my smart phone.

I still can’t resolve this issue.

Any one can help me?