47 lines
2 KiB
Text
47 lines
2 KiB
Text
shader_type canvas_item;
|
|
|
|
// An organic membrane rather than terrain: broad folds move below branching
|
|
// cyan veins. It follows SurfaceBackground's shared camera-uniform contract.
|
|
uniform vec2 camera_cell = vec2(0.0, 0.0);
|
|
uniform vec2 camera_frac = vec2(0.0, 0.0);
|
|
uniform float camera_zoom = 1.0;
|
|
uniform vec2 viewport_size = vec2(720.0, 1280.0);
|
|
uniform float cell_size = 220.0;
|
|
uniform float tile_cells = 32.0;
|
|
uniform vec4 base_color : source_color = vec4(0.055, 0.008, 0.05, 1.0);
|
|
uniform vec4 crater_color : source_color = vec4(0.16, 0.018, 0.10, 1.0);
|
|
uniform vec4 highlight_color : source_color = vec4(0.16, 0.66, 0.72, 1.0);
|
|
|
|
float hash21(vec2 p) {
|
|
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
|
p3 += dot(p3, p3.yzx + 33.33);
|
|
return fract((p3.x + p3.y) * p3.z);
|
|
}
|
|
|
|
void fragment() {
|
|
vec2 screen_px = UV * viewport_size;
|
|
vec2 centered = screen_px - viewport_size * 0.5;
|
|
vec2 rel = camera_frac + centered * (camera_zoom / cell_size);
|
|
vec2 cell_rel = floor(rel);
|
|
vec2 local = rel - cell_rel;
|
|
vec2 wrapped = mod(camera_cell + cell_rel, tile_cells);
|
|
vec2 p = (wrapped + local) / tile_cells * 6.28318530718;
|
|
|
|
float fold_a = sin(p.x * 3.0 + sin(p.y * 2.0 - TIME * 0.16) * 1.1);
|
|
// Integer frequencies on both axes keep the 32-cell wrapped field
|
|
// seamless where p crosses from 2*PI back to zero.
|
|
float fold_b = sin(p.y * 4.0 - p.x * 2.0 + TIME * 0.11);
|
|
float tissue = 0.5 + 0.25 * fold_a + 0.25 * fold_b;
|
|
vec3 color = mix(base_color.rgb, crater_color.rgb, smoothstep(0.18, 0.85, tissue));
|
|
|
|
float vein_a = abs(sin(p.x * 5.0 + sin(p.y * 3.0 + TIME * 0.22)));
|
|
float vein_b = abs(sin(p.y * 6.0 - p.x * 2.0 - TIME * 0.18));
|
|
// Veins are environmental texture, not attack telegraphs. Keep them thin
|
|
// and subdued so the boss's bright pink laser lanes remain unambiguous.
|
|
float vein = 1.0 - smoothstep(0.0, 0.028, min(vein_a, vein_b));
|
|
float pulse = 0.55 + 0.45 * sin(TIME * 1.8 + p.x + p.y);
|
|
color = mix(color, highlight_color.rgb, vein * (0.10 + pulse * 0.20));
|
|
|
|
float dither = (hash21(screen_px + vec2(7.0, 13.0)) - 0.5) / 128.0;
|
|
COLOR = vec4(color + vec3(dither), 1.0);
|
|
}
|