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); }