207 lines
5.3 KiB
Text
207 lines
5.3 KiB
Text
shader_type canvas_item;
|
|
render_mode unshaded;
|
|
|
|
uniform vec4 water_top : source_color = vec4(0.055, 0.38, 0.50, 1.0);
|
|
uniform vec4 water_bottom : source_color = vec4(0.018, 0.16, 0.25, 1.0);
|
|
uniform vec4 caustic_color : source_color = vec4(0.66, 0.91, 0.95, 1.0);
|
|
uniform vec2 pattern_density = vec2(38.0, 21.0);
|
|
uniform vec2 pattern_drift = vec2(0.012, 0.018);
|
|
uniform float mark_opacity_min : hint_range(0.0, 0.1) = 0.022;
|
|
uniform float mark_opacity_max : hint_range(0.0, 0.1) = 0.065;
|
|
uniform sampler2D decorative_bubble_1 : source_color, filter_nearest, repeat_disable;
|
|
uniform sampler2D decorative_bubble_2 : source_color, filter_nearest, repeat_disable;
|
|
uniform sampler2D decorative_bubble_3 : source_color, filter_nearest, repeat_disable;
|
|
uniform float decorative_bubble_opacity : hint_range(0.0, 1.0) = 0.48;
|
|
uniform vec2 rendered_size = vec2(784.0, 394.0);
|
|
uniform float corner_radius : hint_range(0.0, 96.0) = 29.0;
|
|
uniform float corner_softness : hint_range(0.0, 3.0) = 0.75;
|
|
|
|
|
|
float cell_hash(vec2 cell) {
|
|
return fract(sin(dot(cell, vec2(127.1, 311.7))) * 43758.5453);
|
|
}
|
|
|
|
|
|
float block_mark(vec2 point, vec2 half_size) {
|
|
return (
|
|
step(abs(point.x), half_size.x)
|
|
* step(abs(point.y), half_size.y)
|
|
);
|
|
}
|
|
|
|
|
|
vec4 sample_decorative_bubble(
|
|
sampler2D artwork,
|
|
vec2 uv,
|
|
vec2 rect_size,
|
|
vec2 center,
|
|
float logical_size
|
|
) {
|
|
vec2 artwork_uv = (
|
|
(uv - center) * rect_size / logical_size
|
|
+ vec2(0.5)
|
|
);
|
|
float inside = (
|
|
step(0.0, artwork_uv.x)
|
|
* step(artwork_uv.x, 1.0)
|
|
* step(0.0, artwork_uv.y)
|
|
* step(artwork_uv.y, 1.0)
|
|
);
|
|
return texture(artwork, clamp(artwork_uv, vec2(0.0), vec2(1.0))) * inside;
|
|
}
|
|
|
|
|
|
vec2 decorative_bubble_center(
|
|
float base_x,
|
|
float phase,
|
|
float speed,
|
|
float drift_phase
|
|
) {
|
|
float progress = fract(phase + TIME * speed);
|
|
return vec2(
|
|
base_x + sin(TIME * 0.21 + drift_phase) * 0.012,
|
|
1.10 - progress * 1.24
|
|
);
|
|
}
|
|
|
|
|
|
void fragment() {
|
|
vec2 uv = UV;
|
|
vec3 base = mix(water_top.rgb, water_bottom.rgb, smoothstep(0.0, 1.0, uv.y));
|
|
|
|
vec2 flowing_grid = (uv + TIME * pattern_drift) * pattern_density;
|
|
float row = floor(flowing_grid.y);
|
|
flowing_grid.x += mod(row, 2.0) * 0.43;
|
|
vec2 cell = floor(flowing_grid);
|
|
vec2 local = fract(flowing_grid) - vec2(0.5);
|
|
vec2 jitter = vec2(
|
|
cell_hash(cell + vec2(3.7, 9.1)),
|
|
cell_hash(cell + vec2(7.3, 2.9))
|
|
) - vec2(0.5);
|
|
local -= jitter * vec2(0.52, 0.46);
|
|
vec2 stepped_local = (
|
|
floor((local + vec2(0.5)) * 8.0) / 8.0
|
|
- vec2(0.5)
|
|
);
|
|
float shape_key = cell_hash(cell + vec2(13.1, 5.7));
|
|
float size_key = cell_hash(cell + vec2(1.9, 17.3));
|
|
vec2 mark_half_size = mix(
|
|
vec2(0.10, 0.07),
|
|
vec2(0.18, 0.12),
|
|
size_key
|
|
);
|
|
float mark = block_mark(stepped_local, mark_half_size);
|
|
if (shape_key < 0.34) {
|
|
mark = max(
|
|
mark,
|
|
block_mark(
|
|
stepped_local - vec2(mark_half_size.x * 0.8, -0.11),
|
|
vec2(mark_half_size.x * 0.52, 0.045)
|
|
)
|
|
);
|
|
} else if (shape_key < 0.67) {
|
|
mark *= 1.0 - block_mark(
|
|
stepped_local - vec2(mark_half_size.x * 0.7, 0.0),
|
|
vec2(0.045, 0.045)
|
|
);
|
|
} else {
|
|
mark = max(
|
|
mark,
|
|
block_mark(
|
|
stepped_local + vec2(mark_half_size.x * 0.75, 0.10),
|
|
vec2(0.055, 0.04)
|
|
)
|
|
);
|
|
}
|
|
float occupancy = step(
|
|
0.22,
|
|
cell_hash(cell + vec2(19.7, 23.3))
|
|
);
|
|
float mark_opacity = mix(
|
|
mark_opacity_min,
|
|
mark_opacity_max,
|
|
cell_hash(cell + vec2(29.9, 11.5))
|
|
);
|
|
base += caustic_color.rgb * mark * occupancy * mark_opacity;
|
|
|
|
float sheen = (1.0 - smoothstep(0.0, 0.12, uv.y)) * 0.11;
|
|
base += caustic_color.rgb * sheen;
|
|
|
|
vec2 rect_size = max(rendered_size, vec2(1.0));
|
|
float desktop_bubble_slots = step(260.0, rect_size.y);
|
|
vec4 authored_bubbles = vec4(0.0);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_1,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.12, 0.05, 0.020, 0.4),
|
|
22.0
|
|
);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_2,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.27, 0.42, 0.016, 2.1),
|
|
28.0
|
|
);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_3,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.41, 0.76, 0.018, 4.0),
|
|
19.0
|
|
);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_1,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.56, 0.22, 0.015, 5.2),
|
|
25.0
|
|
);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_3,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.69, 0.58, 0.019, 1.3),
|
|
30.0
|
|
);
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_2,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.82, 0.89, 0.017, 3.1),
|
|
21.0
|
|
) * desktop_bubble_slots;
|
|
authored_bubbles += sample_decorative_bubble(
|
|
decorative_bubble_1,
|
|
uv,
|
|
rect_size,
|
|
decorative_bubble_center(0.92, 0.34, 0.014, 6.0),
|
|
24.0
|
|
) * desktop_bubble_slots;
|
|
float authored_alpha = clamp(
|
|
authored_bubbles.a * decorative_bubble_opacity,
|
|
0.0,
|
|
0.72
|
|
);
|
|
vec3 authored_color = (
|
|
authored_bubbles.rgb
|
|
/ max(authored_bubbles.a, 0.001)
|
|
);
|
|
base = mix(base, authored_color, authored_alpha);
|
|
|
|
vec2 half_size = rect_size * 0.5;
|
|
float radius = min(corner_radius, min(half_size.x, half_size.y));
|
|
vec2 rounded_offset = (
|
|
abs(uv * rect_size - half_size)
|
|
- (half_size - vec2(radius))
|
|
);
|
|
float edge_distance = (
|
|
length(max(rounded_offset, vec2(0.0)))
|
|
+ min(max(rounded_offset.x, rounded_offset.y), 0.0)
|
|
- radius
|
|
);
|
|
float softness = max(corner_softness, 0.001);
|
|
float rounded_alpha = 1.0 - smoothstep(-softness, softness, edge_distance);
|
|
COLOR = vec4(base, rounded_alpha);
|
|
}
|