I am trying to create the effect of the water surface thickness with a vertex-fragment shader.

I am in a 3D game environment but It's a scroll view so a "2D" view. Here is a good tutorial of creating such effect in real 2D using fragment shader.
But this can't be used in my case I think. For the moment I have only a plane were I apply refraction.


And I want to apply the water thickness effect. But I don't know how to do it.
I am not trying to create some water deformation/displacement using vertex for the moment, this is not the point.

I don't know if it's possible with a simple quad maybe should I use an object like this.


Here are some examples.

1 2 4 rayman

I don't have any idea on how to create this effect.

Thanks a lot !

[EDIT] Added Rayman water effect to have a better reference of the effect.

  • \$\begingroup\$ How are you doing your water effect currently? If the first screenshot in the post is yours, it looks like you're drawing a 2D quad over the scene, with a shader that distorts it. If that's correct, why can't you follow the instructions in the tutorial, which is also based on using a distorted 2D texture? \$\endgroup\$ Commented May 28, 2013 at 16:38
  • \$\begingroup\$ I have a 3D quad with a vertex-fragment shader that distords the background (the background is captured by Unity GrabPass functionnality). I don't think that using a 2D texture is a good idea, I was thinking of something more generic with customable parameters but it seems there is no other way... and it would be slower no ? \$\endgroup\$
    – MaT
    Commented May 29, 2013 at 6:56

1 Answer 1


Have a value in the shader that specifies wetness. Smaller than 0 means air, greater than 1 means water, and in between means meniscus.

Here is some pseudo code:

vec2 uv2 = bigWaves(uv); // modify the texture coords to create a wavy water effect
float wetness = (uv2.y - 0.1) * 100;

if( wetness<0.0 )
    gl_Fragment = texture2D(screen_texture,uv); // is air - no refraction or effect
else if( wetness>1.0 )
    vec2 uv3 = smallWaves(uv2); // modify the texture coords to create a ripply water effect
    gl_Fragment = texture2D(screen_texture,uv3); // is water - with refraction
    gl_Fragment = vec4(1,1,1,1); // solid white meniscus

This is the simplest I can make it. If it were me, I would do something a bit more complicated to antialias the meniscus and apply more refraction there or something, but I can't tell you what because it would take aesthetic iterations. Also, I would tint and blur the water sample. But I'll leave all that up to you.

  • \$\begingroup\$ Yes, it's a good idea ! I totally agree about blur and tint. I am also adding a depth(Y) gradient (maybe another depth(Z) gradient). I should add a different refraction effect in the meniscus zone too but for the moment I am trying to have a ripple effect like in Rayman. But I don't know how. Maybe I should use different Textures for the meniscus to have this duplicate effect. I don't know if you know what I mean. \$\endgroup\$
    – MaT
    Commented Jun 3, 2013 at 10:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .