Add 2D canvas mode compacted to the steps, ocean-chaos and reef-2d shaders

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
April John 2026-10-16 15:28:41 +02:00
commit d917860201
2 changed files with 252 additions and 12 deletions

51
shaders/ocean-chaos.glsl Normal file
View file

@ -0,0 +1,51 @@
// Slow colourful ocean for the chaos event: the palette drifts through the
// whole colour wheel over a few minutes, jellyfish glide along the stairs,
// plankton fades in and out. Nothing here moves fast.
float hash(float n) { return fract(sin(n * 12.9898) * 43758.5453); }
vec3 hsv(float h, float s, float v) {
vec3 rgb = clamp(abs(mod(h * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0,
0.0, 1.0);
return v * mix(vec3(1.0), rgb, s);
}
// A jellyfish: soft blob that glides and breathes
vec3 jelly(float i, float t, float seed) {
float pos = 6.0 + 5.5 * sin(t * (0.07 + 0.03 * seed) + seed * 4.0);
float d = i - pos;
float breath = 0.55 + 0.45 * sin(t * 0.5 + seed * 3.0);
float hue = 0.85 + 0.35 * seed + t / 180.0; // contrasts with the water
return hsv(hue, 0.7, 1.0) * exp(-d * d * 0.55) * breath * 0.75;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
float i = floor(fragCoord.x / iResolution.x * 16.0);
float t = iTime;
// waves, all slow
float w1 = 0.5 + 0.5 * sin(i * 0.55 - t * 0.45);
float w2 = 0.5 + 0.5 * sin(i * 0.90 + t * 0.30 + 1.0);
float w3 = 0.5 + 0.5 * sin(i * 0.25 - t * 0.17 + 2.5);
float h = 0.45 * w1 + 0.30 * w2 + 0.25 * w3;
// water colour: blue to magenta to teal, wheel drifts over 3 minutes
float hue = 0.58 + 0.22 * sin(i * 0.22 + t * 0.06) + 0.10 * h + t / 180.0;
vec3 col = hsv(hue, 0.95, 0.10 + 0.75 * h);
// foam on the crests
float foam = smoothstep(0.80, 0.97, h);
col = mix(col, vec3(0.9), foam * 0.7);
// jellyfish
col += jelly(i, t, 0.0) + jelly(i, t, 1.0);
// plankton, each step lights up now and then for ~12 s
float cyc = t * 0.08 + hash(i);
float cell = floor(cyc);
float life = sin(3.14159265 * fract(cyc));
float on = step(0.72, hash(i * 13.0 + cell));
col += hsv(hue + 0.5, 0.4, 1.0) * pow(life, 4.0) * on * 0.55;
fragColor = vec4(col, 1.0);
}

46
shaders/reef-2d.glsl Normal file
View file

@ -0,0 +1,46 @@
// canvas: 256x48 compact: mean
//
// A real 2D picture, compacted to the stairs by treppe-gl: every step is the
// average of a 16 pixel wide column of the canvas. Fish swim through slowly,
// caustics ripple near the surface, the colours drift around the wheel.
float hash(float n) { return fract(sin(n * 12.9898) * 43758.5453); }
vec3 hsv(float h, float s, float v) {
vec3 rgb = clamp(abs(mod(h * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0,
0.0, 1.0);
return v * mix(vec3(1.0), rgb, s);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy; // 0..1, y up
float t = iTime;
float drift = t / 180.0;
// water, darker towards the bottom
vec3 col = hsv(0.55 + drift + 0.08 * sin(uv.x * 3.0 + t * 0.05),
0.95, 0.12 + 0.55 * uv.y);
// caustics near the surface
float c = sin(uv.x * 60.0 + t * 0.4 + 2.0 * sin(uv.y * 8.0 + t * 0.3))
* sin(uv.x * 41.0 - t * 0.3 + uv.y * 6.0);
col += hsv(0.50 + drift, 0.4, 1.0) * pow(max(c, 0.0), 3.0) * uv.y * 0.5;
// fish
for (int k = 0; k < 5; k++) {
float fk = float(k);
float speed = 0.02 + 0.015 * hash(fk + 1.0); // screen widths / s
float dir = mod(fk, 2.0) < 1.0 ? 1.0 : -1.0;
float fx = fract(t * speed * dir + fk * 0.23) * 1.4 - 0.2;
float fy = 0.25 + 0.5 * hash(fk + 7.0) + 0.05 * sin(t * 0.5 + fk);
vec2 d = vec2((uv.x - fx) / 0.10, (uv.y - fy) / 0.30);
float body = 1.0 - smoothstep(0.7, 1.0, length(d));
// tail behind the fish
vec2 dt = vec2((uv.x - (fx - dir * 0.09)) / 0.04, (uv.y - fy) / 0.22);
float tail = 1.0 - smoothstep(0.6, 1.0, length(dt));
vec3 fc = hsv(hash(fk + 3.0) + 0.5 + drift, 0.85, 1.0);
col = mix(col, fc, clamp(body + 0.8 * tail, 0.0, 1.0) * 0.9);
}
fragColor = vec4(col, 1.0);
}