summaryrefslogblamecommitdiffstats
path: root/water/Wave.gdshader
blob: 06c532764a5c1d19b7d51024ef794541eb6b3c5c (plain) (tree)
1
2
3
4
5
6
7
8
9


                                             
                                       
                                       
                            
 
                                       
                                       
                            
 
                                       
                                       
                            
 





                                      
 
                              
                                       
 



                           
 
                                                                                                        



                             






























                                      
                                                          

                                 




                                                                                          


                                                










                                                                











                                                             








                                                                        
                                                                             

                                           








                                                                                            


                                                                                                    
                                                                                               
                                        

                                                                           
                        





                                                           
                                     
                                                                             
                                                                            
 
shader_type spatial;
render_mode cull_disabled, depth_draw_always;

uniform vec3 wave1 = vec3(0.5,0.5,0.5);
uniform vec2 wave1_dir = vec2(1.0,0.0);
uniform float wave1_t = 0.0;

uniform vec3 wave2 = vec3(0.5,0.5,0.5);
uniform vec2 wave2_dir = vec2(1.0,0.0);
uniform float wave2_t = 0.0;

uniform vec3 wave3 = vec3(0.5,0.5,0.5);
uniform vec2 wave3_dir = vec2(1.0,0.0);
uniform float wave3_t = 0.0;

uniform vec4 water_color : hint_color;

uniform vec4 foam_color: hint_color;
uniform sampler2D foam_map;
uniform float foam_amount_edge = 2.0;
uniform float foam_amount_crest = 4.0;

uniform float murkiness = 4.0;
uniform float refraction_amount = 0.01;

uniform sampler2D noise;

varying vec3 global_vertex;
varying vec3 displacement;

vec3 gerstner_wave(vec3 wave, vec2 wave_dir, float t, vec3 pos, inout vec3 tangent, inout vec3 binormal)
{
    float steepness = wave.x;
    float k = wave.y;
    float a = wave.z;

    vec2 d = normalize(wave_dir);
    float f = k * (dot(d,pos.xz) - t);

    float tmp1 = steepness * sin(f);
    float tmp2 = steepness * cos(f);

    tangent += vec3(
        -d.x * d.x * tmp1,
        d.x * tmp2,
        -d.x * d.y * tmp1
       );

    binormal += vec3(
        -d.x * d.y * tmp1,
        d.y * tmp2,
        -d.y * d.y * tmp1
       );

    float tmp3 = a * cos(f);
    vec3 new_pos = vec3(
        d.x * tmp3,
        a * sin(f),
        d.y * tmp3
       );

    return new_pos;
}

void vertex()
{
    global_vertex = (WORLD_MATRIX * vec4(VERTEX,1.0)).xyz;
    TANGENT = vec3(1.0,0.0,0.0);
    BINORMAL = vec3(0.0,0.0,1.0);
    displacement = vec3(0.0,0.0,0.0);
    displacement += gerstner_wave(wave1,wave1_dir,wave1_t,global_vertex,TANGENT,BINORMAL);
    displacement += gerstner_wave(wave2,wave2_dir,wave2_t,global_vertex,TANGENT,BINORMAL);
    displacement += gerstner_wave(wave3,wave3_dir,wave3_t,global_vertex,TANGENT,BINORMAL);
    VERTEX += displacement;
    NORMAL = normalize(cross(BINORMAL,TANGENT));
}

float get_depth(vec2 coords, sampler2D tex, mat4 proj)
{
    float depth = texture(tex, coords).r;
    vec3 depth_coords_clip = vec3(coords, depth);
    depth_coords_clip = depth_coords_clip * 2.0 - 1.0;
    vec4 depth_coords_view = proj * vec4(depth_coords_clip,1.0);
    depth_coords_view.xyz /= depth_coords_view.w;
    depth = -depth_coords_view.z;
    return depth;
}

const float pi = 3.1415;
const float tau = pi * 2.0;

float wave_position(float k,vec2 dir,float t)
{
    float pos = k * (dot(normalize(dir),global_vertex.xz)-t);
    pos = mod(pos-pi,tau);
    pos = clamp(pos,0.0,tau);
    pos = 1.0 - (0.5*cos(0.159*pow(pos,2.0))+0.5);
    return pos;
}

void fragment()
{
    ALPHA = 1.0;
    SPECULAR = 0.4;
    ROUGHNESS = 0.05;

    NORMALMAP = texture(noise, UV + (TIME * vec2(-1.0,0.0) * 0.05)).xyz;
    NORMALMAP_DEPTH = 0.3;

    float depth = get_depth(SCREEN_UV, DEPTH_TEXTURE, INV_PROJECTION_MATRIX);
    float water_depth = -VERTEX.z;
    float submersion = depth - water_depth;
    float wave_pos = wave_position(wave1.y,wave1_dir,wave1_t);
    wave_pos *= wave_position(wave2.y,wave2_dir,wave2_t);
    wave_pos *= wave_position(wave3.y,wave3_dir,wave3_t);
    wave_pos = 1.0 - (pow(1.0 - wave_pos, foam_amount_crest));
    vec4 foam = texture(foam_map, UV + (-displacement.xz * 0.001));
    vec4 mapped_foam_color = mix(water_color,foam_color,foam.b);
    vec4 color = mix(water_color, mapped_foam_color, wave_pos);
    float object_foam = clamp((foam_amount_edge - submersion) / foam_amount_edge, 0.0, 1.0);
    ALBEDO = mix(color, vec4(1.0), object_foam).rgb;

    vec3 oriented_normalmap = vec3(TANGENT*NORMALMAP.x + NORMAL*NORMALMAP.y + BINORMAL*NORMALMAP.z);
    vec3 normal = normalize(mix(NORMAL,oriented_normalmap,NORMALMAP_DEPTH));
    vec2 refraction_uv = SCREEN_UV + (normal.xz * (refraction_amount / exp(water_depth/20.0)));
    float murky = murkiness * ROUGHNESS;
    depth = get_depth(refraction_uv, DEPTH_TEXTURE, INV_PROJECTION_MATRIX);
    submersion = depth - water_depth;
    murky *= submersion;
    float depth_visibility = 0.0;
    if(submersion >= 0.0)
    {
        depth_visibility = exp(-murky);
        depth_visibility = clamp(depth_visibility,0.0,1.0);
    }
    float depth_scatter = exp(murky);
    vec4 bg_color = textureLod(SCREEN_TEXTURE, refraction_uv, depth_scatter);
    EMISSION = mix(color, bg_color, depth_visibility).rgb * (1.0 - color.a);
}