netmasked/shaders/water.gdshader

66 lines
No EOL
2.2 KiB
Text

shader_type canvas_item;
// --- Uniforms ---
uniform vec4 target_color : source_color = vec4(0.0, 0.0, 1.0, 1.0);
uniform float tolerance : hint_range(0.0, 1.0) = 0.1;
uniform vec4 water_deep_color : source_color = vec4(0.0, 0.4, 0.8, 1.0);
uniform vec4 foam_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
// --- Functions ---
vec2 random(vec2 uv) {
return vec2(fract(sin(dot(uv.xy, vec2(12.9898,78.233))) * 43758.5453123));
}
float worley(vec2 uv, float columns, float rows) {
vec2 index_uv = floor(vec2(uv.x * columns, uv.y * rows));
vec2 fract_uv = fract(vec2(uv.x * columns, uv.y * rows));
float minimum_dist = 1.0;
for (int y= -1; y <= 1; y++) {
for (int x= -1; x <= 1; x++) {
vec2 neighbor = vec2(float(x),float(y));
vec2 point = random(index_uv + neighbor);
vec2 diff = neighbor + point - fract_uv;
float dist = length(diff);
minimum_dist = min(minimum_dist, dist);
}
}
return minimum_dist;
}
float noise(vec2 uv) {
vec2 uv_index = floor(uv);
vec2 uv_fract = fract(uv);
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
return mix( mix( dot( random(uv_index + vec2(0.0,0.0) ), uv_fract - vec2(0.0,0.0) ),
dot( random(uv_index + vec2(1.0,0.0) ), uv_fract - vec2(1.0,0.0) ), blur.x),
mix( dot( random(uv_index + vec2(0.0,1.0) ), uv_fract - vec2(0.0,1.0) ),
dot( random(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) + 0.5;
}
varying vec2 world_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0, 1.0)).xy;
}
void fragment() {
vec4 tex_color = texture(TEXTURE, UV);
float color_diff = distance(tex_color.rgb, target_color.rgb);
if (color_diff < tolerance) {
vec2 w_uv = world_pos * 0.01;
float noise_value = noise(world_pos * 0.1 - TIME * 0.1) * 0.1;
w_uv.x += noise_value;
float worley_val = worley(w_uv + TIME * 0.1, 6.0, 10.0);
vec4 final_water = mix(water_deep_color, foam_color, step(0.7, worley_val));
COLOR = vec4(final_water.rgb, tex_color.a);
} else {
COLOR = tex_color;
}
}