46 lines
1.9 KiB
GLSL
46 lines
1.9 KiB
GLSL
// 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);
|
|
}
|