V-Panel/shaders/vial_fill.gdshader

166 lines
6.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

shader_type canvas_item;
// --- Fill control ---
uniform float fill : hint_range(0.0, 1.0) = 0.0;
uniform vec4 bg_color : source_color = vec4(0.08, 0.08, 0.12, 1.0);
uniform vec4 border_color : source_color = vec4(0.2, 0.2, 0.28, 1.0);
uniform float corner_radius : hint_range(0.0, 0.5) = 0.05;
uniform float border_width : hint_range(0.0, 0.1) = 0.008;
uniform float wave_amp : hint_range(0.0, 0.05) = 0.012;
uniform float wave_freq : hint_range(0.0, 15.0) = 4.0;
// --- Liquid base color (modulated by effects below) ---
uniform vec4 liquid_color : source_color = vec4(0.2, 0.5, 0.8, 1.0);
// --- Animation controls ---
uniform float time_factor : hint_range(0.0, 5.0) = 1.0;
uniform float wave_strength : hint_range(0.0, 0.5) = 0.05;
uniform float ripple_speed : hint_range(0.0, 5.0) = 1.0;
// --- Glow / edge ---
uniform vec4 edge_color : source_color = vec4(0.3, 0.6, 1.0, 1.0);
uniform float glow_intensity : hint_range(0.0, 5.0) = 1.5;
uniform float edge_pulse : hint_range(0.0, 2.0) = 1.0;
// --- Distortion ---
uniform sampler2D noise_tex : repeat_enable;
uniform float noise_scale : hint_range(0.0, 5.0) = 1.0;
uniform vec2 noise_module_size = vec2(300.0, 240.0);
uniform float swirl_strength : hint_range(-2.0, 2.0) = 0.5;
uniform float hue_shift_speed : hint_range(0.0, 5.0) = 0.0;
// ---------- helpers ----------
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1e-10;
return vec3(abs((q.w - q.y) / (6.0 * d + e) + q.z), d / (q.x + e), q.x);
}
vec3 hsv2rgb(vec3 c) {
vec3 p = abs(fract(c.xxx + vec3(0.0, 1.0 / 3.0, 2.0 / 3.0)) * 6.0 - 3.0);
return c.z * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), c.y);
}
vec2 get_swirl_uv(vec2 uv, float strength) {
vec2 center = vec2(0.5);
vec2 diff = uv - center;
float dist = length(diff);
float angle = atan(diff.y, diff.x) + strength * (0.5 - dist) * sin(TIME * 0.5);
return center + vec2(cos(angle), sin(angle)) * dist;
}
float rr_sdf(vec2 p, vec2 half_size, float r) {
vec2 d = abs(p) - half_size + r;
return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - r;
}
// ---------- main ----------
void fragment() {
vec2 half_size = vec2(0.5, 0.5);
vec2 uv_centered = UV - half_size;
float t = TIME * time_factor;
// --- rounded-rect mask ---
float max_r = min(corner_radius, half_size.x);
float outer_d = rr_sdf(uv_centered, half_size, max_r);
float outer = 1.0 - smoothstep(0.0, max(0.001, fwidth(outer_d)), max(outer_d, 0.0));
float inner_r = max(0.0, max_r - border_width);
float inner_hw = max(0.0, half_size.x - border_width);
float inner_hh = max(0.0, half_size.y - border_width);
float inner_d = rr_sdf(uv_centered, vec2(inner_hw, inner_hh), inner_r);
float inner = 1.0 - smoothstep(0.0, max(0.001, fwidth(inner_d)), max(inner_d, 0.0));
// --- liquid fill line (sum-of-sines + edge damping) ---
float wf = wave_freq * 6.283;
float w1 = sin(UV.x * wf + TIME * 5.0);
float w2 = sin(UV.x * wf * 1.7 + TIME * 7.0 + 1.3) * 0.5;
float w3 = sin(UV.x * wf * 0.6 + TIME * 2.5 + 2.9) * 0.3;
float wave_sum = (w1 + w2 + w3) / 1.8;
// damp wave near left/right walls for meniscus effect
float edge_damp = smoothstep(0.0, 0.08, UV.x) * smoothstep(0.0, 0.08, 1.0 - UV.x);
wave_sum *= edge_damp;
float fill_line = 1.0 - fill + wave_sum * wave_amp;
float liquid = smoothstep(fill_line - 0.001, fill_line + 0.001, UV.y);
liquid *= inner;
// --- build effect colour for the liquid region ---
vec2 uv = UV;
// Pixel-space noise coordinate: same pixel distance = same noise delta,
// keeping the pattern fixed-size regardless of module aspect or window size.
// The 100.0 constant matches the noise texture size (100×100).
vec2 noise_uv = uv * noise_module_size / 100.0 * noise_scale + t * 0.05;
float noise_val = texture(noise_tex, noise_uv).r;
// wave distortion
uv.y += sin(uv.x * 10.0 + t) * wave_strength * noise_val;
uv.x += cos(uv.y * 10.0 + t * 0.5) * wave_strength * noise_val;
// ripple rings
float dist_center = distance(uv, vec2(0.5));
uv += sin(dist_center * 20.0 - t * ripple_speed) * (wave_strength * 0.5 * noise_val);
// swirl
uv = get_swirl_uv(uv, swirl_strength);
// Sample the noise at the distorted UV for visible liquid variation.
// (ColorRect has no texture, so TEXTURE is always white — this makes
// wave/ripple/swirl deformation visible by sampling noise instead.)
float detail = texture(noise_tex, (uv * noise_module_size / 100.0 * noise_scale + t * 0.03) * 0.5).r;
vec3 base_rgb = liquid_color.rgb * (0.85 + 0.15 * detail);
vec3 hsv = rgb2hsv(base_rgb);
hsv.x = fract(hsv.x + t * 0.1 * hue_shift_speed);
hsv.y = clamp(hsv.y + 0.2 * noise_val, 0.0, 1.0);
vec3 effect_rgb = hsv2rgb(hsv);
// top-down lighting — subtle brightening at the very top
float top_light = smoothstep(0.0, 0.3, 1.0 - UV.y);
effect_rgb *= 1.0 + top_light * 0.2;
// overall pulse
float pulse = 0.8 + 0.2 * sin(t);
effect_rgb *= (glow_intensity * pulse);
// tiny sparkle
effect_rgb += 0.03 * vec3(sin(t * 3.0), cos(t * 2.0), noise_val * 0.1);
// --- 3D water surface ---
float d_surf = UV.y - fill_line; // positive = below surface
float d_abs = abs(d_surf);
// subsurface light scatter — brightest just below surface, fades with depth
float subsurface = exp(-d_surf * 25.0) * step(0.0, d_surf);
effect_rgb *= 1.0 + subsurface * 0.25;
// --- composite ---
vec3 col = bg_color.rgb;
col = mix(col, effect_rgb, liquid);
// foam glow — smooth double-sided falloff (gaussian-like)
float foam_glow = exp(-d_abs * 70.0);
float foam_core = exp(-d_abs * 350.0);
vec3 foam_tint = vec3(0.6, 0.75, 0.95);
col += foam_glow * foam_tint * 0.5;
col += foam_core * vec3(0.75, 0.9, 1.0) * 0.6;
// wave-slope highlight — brightens at wave crests facing the viewer
float wave_slope = (cos(UV.x * wf + TIME * 5.0) * wf
+ cos(UV.x * wf * 1.7 + TIME * 7.0 + 1.3) * wf * 1.7 * 0.5
+ cos(UV.x * wf * 0.6 + TIME * 2.5 + 2.9) * wf * 0.6 * 0.3) * edge_damp / 1.8 * wave_amp;
float slope_highlight = max(0.0, wave_slope) * exp(-d_abs * 200.0);
col += slope_highlight * vec3(0.6, 0.8, 1.0) * 0.4;
// border
col = mix(col, border_color.rgb, outer - inner);
COLOR = vec4(col, outer);
}