shader_type spatial;
render_mode cull_disabled, depth_draw_always;
uniform vec4 wave1 = vec4(0.5,0.5,0.5,1.0);
uniform vec2 wave1_dir = vec2(1.0,0.0);
uniform vec4 wave2 = vec4(0.5,0.5,0.5,1.0);
uniform vec2 wave2_dir = vec2(1.0,0.0);
uniform vec4 wave3 = vec4(0.5,0.5,0.5,1.0);
uniform vec2 wave3_dir = vec2(1.0,0.0);
uniform vec4 water_colour: hint_color;
uniform vec4 deep_water_colour : hint_color;
uniform sampler2D noise;
uniform float foam_amount = 0.6;
uniform float murkiness = 4.0;
uniform float refraction_amount = 0.01;
varying float vertex_y;
vec3 gerstner_wave(vec4 wave, vec2 wave_dir, vec3 pos, inout vec3 tangent, inout vec3 binormal)
{
float steepness = wave.x;
float k = wave.y;
float a = wave.z;
float t = wave.w;
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()
{
vec3 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);
VERTEX += gerstner_wave(wave1,wave1_dir,global_vertex,TANGENT,BINORMAL);
VERTEX += gerstner_wave(wave2,wave2_dir,global_vertex,TANGENT,BINORMAL);
VERTEX += gerstner_wave(wave3,wave3_dir,global_vertex,TANGENT,BINORMAL);
vertex_y = VERTEX.y;
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;
}
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;
vec4 water_color = mix(deep_water_colour, water_colour, clamp(vertex_y,0.0,1.0));
float foam = clamp((foam_amount - submersion) / foam_amount, 0.0, 1.0);
ALBEDO = mix(water_color, vec4(1.0), 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(water_color, bg_color, depth_visibility).rgb * (1.0 - water_color.a);
}