// Hollow Tide, a stand-in world from zaisma.com/developers/backgrounds. MIT licensed: free to start from. float h1(float n) { return fract(sin(n * 127.1) * 43758.5453); } float h2(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); } vec2 h22(vec2 p) { p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3))); return fract(sin(p) * 43758.5453); } float noise(vec2 p) { vec2 i = floor(p), f = fract(p); vec2 u = f * f * (3.0 - 2.0 * f); return mix(mix(h2(i), h2(i + vec2(1.0, 0.0)), u.x), mix(h2(i + vec2(0.0, 1.0)), h2(i + vec2(1.0, 1.0)), u.x), u.y); } float fbm(vec2 p) { float v = 0.0, a = 0.5; for (int i = 0; i < 5; i++) { v += a * noise(p); p = p * 2.03 + 1.7; a *= 0.5; } return v; } // Soft particles in a grid of cells: each cell holds at most one, at a random spot, drifting with the grid. float motes(vec2 p, float size, float chance, float seed) { vec2 id = floor(p), f = fract(p) - 0.5; vec2 r = h22(id + seed) - 0.5; float on = step(1.0 - chance, h2(id + seed * 1.3)); float d = length(f - r * 0.7); return on * smoothstep(size, 0.0, d); } float sat(float x) { return clamp(x, 0.0, 1.0); } float fill(float d, float e) { return smoothstep(e, -e, d); } float smin(float a, float b, float k) { float h = sat(0.5 + 0.5 * (b - a) / k); return mix(b, a, h) - k * h * (1.0 - h); } float seg(vec2 p, vec2 a, vec2 b, float r) { vec2 pa = p - a, ba = b - a; return length(pa - ba * sat(dot(pa, ba) / dot(ba, ba))) - r; } // A limb: two capsules, a to b to c. float limb(vec2 u, vec2 a, vec2 b, vec2 c, float r) { return min(seg(u, a, b, r), seg(u, b, c, r * 0.8)); } // A lamp beam at angle a around the tower (0 = right, pi/2 = toward us). float beam(vec2 q, float a) { float c = cos(a), u = q.x * sign(c), w = 0.005 + max(u, 0.0) * (0.48 - 0.4 * abs(c)), y = q.y + u * 0.035; return exp(-y * y / (w * w) - max(u, 0.0) / (0.06 + 1.4 * abs(c))) * smoothstep(-0.004, 0.012, u) * (0.5 + 0.4 * sin(a)); } // Glitter on the far swells: rows of slow-twinkling dashes; rows under ~3 px melt into a soft line. float dashes(vec2 p, float d, float t) { float v = sqrt(d + 0.004) * 60.0, row = floor(v), rc = (row + 0.5) / 60.0; float x = (p.x + h1(row) * 7.0 + t * 0.003) / (0.06 * rc + 0.003), hr = h2(vec2(floor(x), row)), len = 0.15 + 0.25 * hr; float dash = smoothstep(len, len - 0.12, abs(fract(x) - 0.5 - (hr - 0.5) * 0.4)) * smoothstep(0.5, 0.1, abs(fract(v) - 0.5)) * step(0.35, fract(hr * 13.7)); return mix(0.35, dash * sat(sin(t * (0.5 + hr) + hr * 40.0) * 1.4 + 0.4), smoothstep(2.5, 5.0, rc / 30.0 * iResolution.y)); } // The drowned body (feet 0, crown 1): limp, arms drifting up, torn shirt and hair streaming. float body(vec2 u, float t) { float l = 0.03 * sin(t * 0.45), m = 0.03 * sin(t * 0.37 + 1.0), cy = sat((0.66 - u.y) / 0.3); float d = smin(length((u - vec2(0.075, 0.79)) / vec2(0.85, 1.1)) - 0.06, seg(u, vec2(0.03, 0.7), vec2(-0.02, 0.45), 0.072), 0.05); d = smin(d, limb(u, vec2(-0.05, 0.69), vec2(-0.14, 0.83 + l), vec2(-0.1 + l, 0.97 + l), 0.032), 0.04); d = smin(d, limb(u, vec2(0.09, 0.68), vec2(0.2, 0.76 - m), vec2(0.26 + m, 0.9), 0.032), 0.04); d = smin(d, limb(u, vec2(-0.03, 0.46), vec2(-0.08, 0.23), vec2(-0.05 + m, 0.03), 0.042), 0.04); d = smin(d, limb(u, vec2(0.04, 0.46), vec2(0.11, 0.26), vec2(0.17 + l, 0.11), 0.042), 0.04); float hem = 0.34 + 0.04 * sin(u.x * 30.0 - t * 1.1) + 0.025 * sin(u.x * 61.0 + t * 0.7); d = smin(d, max(abs(u.x - 0.02 - 0.07 * cy * cy - 0.02 * sin(t * 0.5)) - mix(0.075, 0.16, cy), max(u.y - 0.7, hem - u.y)), 0.02); vec2 dir = vec2(-0.682, 0.732), e = u - vec2(0.07, 0.82); for (int i = 0; i < 6; i++) { // hair: a fan of slow, wavering strands float fi = float(i), al = dot(e, dir), ac = dot(e, vec2(dir.y, -dir.x)) - 0.7 * al * al - 0.16 * al * sin(al * 15.0 - t * 0.9 + fi * 1.3); d = min(d, max(abs(ac) - mix(0.017, 0.006, sat(al / 0.3)), max(-al, al - 0.24 - 0.08 * fract(fi * 0.618)))); dir = mat2(0.964, -0.267, 0.267, 0.964) * dir; } return d; } void mainImage(out vec4 color, in vec2 pixel) { float ar = iResolution.x / iResolution.y, wide = smoothstep(0.7, 1.5, ar), px = 1.5 / iResolution.y, t = iTime; vec2 p = pixel / iResolution.y; float wl0 = mix(0.6, 0.46, wide), hz = wl0 + 0.05, sc = mix(0.72, 1.0, wide); float wl = wl0 + 0.011 * sin(p.x * 5.0 - t * 0.9) + 0.005 * sin(p.x * 13.0 + t * 1.3) + 0.0025 * sin(p.x * 29.0 - t * 2.1); vec2 moon = vec2(mix(0.26, 0.42, wide) * ar, mix(0.91, 0.69, wide)); float lx = mix(0.68, 0.7, wide) * ar, rx = p.x - lx, dm = length(p - moon), top = wl0 + mix(0.23, 0.24, wide), a = mod(t, 32.0) * 0.19635; vec2 lamp = vec2(lx, top + 0.016); // Where the two beams (one turn in 32 s) fall on the water. float onSea = 0.0; for (int b = 0; b < 2; b++) { float ab = a + float(b) * 3.1416, u = rx * sign(cos(ab)); onSea += exp(-max(u, 0.0) / (0.05 + 1.2 * abs(cos(ab)))) * smoothstep(-0.02, 0.03, u) * (0.5 + 0.4 * sin(ab)); } float fogN = noise(vec2(p.x * 2.2 - t * 0.045, p.y * 6.0 + sin(p.x * 1.3 + t * 0.03))) * 0.6 + noise(vec2(p.x * 5.0 - t * 0.085, p.y * 13.0)) * 0.4; vec3 col; if (p.y > wl) { if (p.y > hz) { // Sky: haze, halo, stars, cloud streaks, a far headland. float k = sat((p.y - hz) / (1.0 - hz)), hx = sat(1.0 - p.x / ar * 1.75); col = mix(vec3(0.08, 0.27, 0.27), vec3(0.008, 0.035, 0.045), pow(k, 0.6)) + vec3(0.1, 0.2, 0.19) * exp(-dm * 2.2) + vec3(0.2, 0.28, 0.26) * exp(-dm * 7.0) + vec3(0.4, 0.45, 0.42) * exp(-dm * 30.0); vec2 sg = p * 70.0; col += vec3(0.8, 0.95, 0.95) * motes(sg, 0.13, 0.08, 3.0) * (0.6 + 0.4 * sin(t * 1.1 + h2(floor(sg)) * 40.0)) * smoothstep(0.2, 0.5, k) * smoothstep(0.12, 0.3, dm); col = mix(col, vec3(0.08, 0.17, 0.18) + vec3(0.6, 0.72, 0.68) * exp(-dm * 4.0), smoothstep(0.5, 0.8, fogN) * smoothstep(1.0, 0.7, p.y) * smoothstep(hz + 0.08, hz + 0.18, p.y) * 0.6); col = mix(col, vec3(0.05, 0.18, 0.19), fill(p.y - hz - (0.028 * hx + 0.007 * sin(p.x * 11.0) + 0.004 * sin(p.x * 23.0 + 1.0)) * hx, px) * 0.8); // The moon, mottled, veiled by passing mist. vec2 mq = (p - moon) / 0.046; vec3 mc = vec3(0.95, 0.97, 0.9) - vec3(0.17, 0.15, 0.12) * smoothstep(0.42, 0.72, noise(mq * 1.7 + 3.0) * 0.65 + noise(mq * 4.3 + 9.0) * 0.35) - 0.1 * dot(mq, mq); col = mix(col, mix(mc, vec3(0.5, 0.62, 0.6), smoothstep(0.55, 0.85, fogN) * 0.35), fill(dm - 0.046, px)); } else { // The far sea: swells, the moon's glitter path, beam light. float d = hz - p.y, gw = (p.x - moon.x) / (0.02 + d * 1.6), swl = 0.5 + 0.5 * sin(0.15 / (d + 0.004) + t * 0.6 + sin(p.x * 3.0) * 1.5); col = mix(vec3(0.08, 0.26, 0.26), vec3(0.015, 0.06, 0.07), sat(d * 25.0)) + vec3(0.03, 0.1, 0.1) * swl * smoothstep(0.004, 0.018, d); col += vec3(0.85, 0.96, 0.92) * (exp(-gw * gw) * dashes(p, d, t) * (0.6 + 0.6 * swl) + exp(-gw * gw * 0.15) * 0.08) + vec3(0.8, 0.92, 0.85) * onSea * (0.25 + 0.5 * swl) * smoothstep(0.0, 0.02, d); } // The crag; the banded tower, gallery, roof and lamp. float sh = sat(1.0 - pow(rx / (0.115 * mix(0.8, 1.0, wide)), 2.0)), rockTop = wl0 + sh * (0.062 + 0.022 * abs(sin(rx * 30.0 + 1.0)) + 0.006 * sin(rx * 97.0)); col = mix(col, vec3(0.01, 0.022, 0.026) + vec3(0.12, 0.2, 0.19) * smoothstep(0.012, 0.0, rockTop - p.y) * sat(0.5 - rx * 8.0), fill(p.y - rockTop, px) * step(0.001, sh)); float ty = (p.y - wl0 - 0.066) / (top - wl0 - 0.066), hw = mix(0.018, 0.011, ty); col = mix(col, mix(vec3(0.07, 0.11, 0.11), vec3(0.015, 0.03, 0.035), sat((rx + hw) / hw)) * (0.75 + 0.25 * step(0.5, fract(ty * 3.0))), fill(abs(rx) - hw, px) * step(0.0, ty) * step(ty, 1.0)); float roof = max(fill(abs(rx) - 0.02, px) * fill(abs(p.y - top - 0.003) - 0.003, px), fill(abs(rx) - 0.012 * sat((top + 0.04 - p.y) / 0.015), px) * step(top + 0.025, p.y) * step(p.y, top + 0.04)); col = mix(mix(col, vec3(0.02, 0.035, 0.04), roof), vec3(1.0, 0.96, 0.82), fill(abs(rx) - 0.01, px) * fill(abs(p.y - top - 0.016) - 0.009, px)); // A fog bank on the horizon and a thin layer at lamp height; the beams and the glare. float bankTop = hz + 0.03 + 0.035 * noise(vec2(p.x * 2.4 - t * 0.035, 4.0)) + 0.03 * (fogN - 0.5); float fog = sat(smoothstep(-0.02, 0.05, bankTop - p.y) * (0.2 + 0.8 * fogN) * smoothstep(wl0 - 0.01, hz, p.y) + exp(-pow((p.y - lamp.y) / 0.08, 2.0)) * smoothstep(0.35, 0.85, fogN) * 0.55); col = mix(col, vec3(0.16, 0.27, 0.27) + vec3(0.3, 0.36, 0.33) * exp(-dm * 2.2) + vec3(0.1, 0.14, 0.13) * smoothstep(0.03, 0.0, abs(bankTop - p.y)), fog * 0.6); vec2 q = p - lamp; float dl = length(q * vec2(1.0, 1.6)); col += vec3(0.85, 0.95, 0.88) * (beam(q, a) + beam(q, a + 3.1416)) * (0.35 + 1.3 * fog + 0.3 * fogN) + vec3(1.0, 0.95, 0.82) * (exp(-dl * 60.0) * 0.8 + exp(-dl * 14.0) * (0.12 + 0.35 * pow(abs(sin(a)), 6.0))); } else { // Under water: green-teal into black, moon shafts, far stacks, a glow in the deep, marine snow. float dd = wl - p.y, sx = p.x - dd * 0.32, bx = p.x / ar; vec3 water = mix(vec3(0.05, 0.21, 0.2), vec3(0.002, 0.012, 0.015), sat(pow(dd / wl0, 0.6))); float rays = smoothstep(0.5, 0.85, noise(vec2(sx * 9.0, t * 0.12)) * 0.6 + noise(vec2(sx * 21.0, t * 0.2 + 4.0)) * 0.4) * exp(-dd * 3.5) * (0.35 + 0.65 * exp(-pow((sx - moon.x) / 0.55, 2.0))); col = water + vec3(0.14, 0.25, 0.22) * exp(-pow((sx - moon.x) / (0.14 + dd * 0.3), 2.0) - dd * 3.0) + vec3(0.16, 0.34, 0.3) * rays; col = mix(col, vec3(0.01, 0.04, 0.045), fill(p.y - 0.16 - 0.09 * sat(sin(p.x * 3.1 + 0.6)) - 0.012 * sin(p.x * 17.0) + 0.12 * smoothstep(0.35, 0.6, bx), px) * 0.6); float dy = p.y - mix(0.34, 0.14, wide) - 0.045 * sin(bx * 5.0 + t * 0.12) - 0.02 * sin(bx * 11.0 - t * 0.09); col += vec3(0.03, 0.15, 0.1) * exp(-pow((dy - 0.06) / 0.2, 2.0)) * smoothstep(0.0, 0.5, bx) + vec3(0.16, 0.23, 0.21) * motes(p * 42.0 + vec2(sin(t * 0.2) * 0.5, t * 0.12), 0.13, 0.15, 7.0) * exp(-dd * 1.5); // The leviathan: a vast ridged back blotting out the glow, a slow wave through its lights. float thick = 0.015 + 0.12 * smoothstep(0.0, 1.0, bx), ridge = 0.022 * pow(abs(sin(p.x * 21.0)), 5.0) * smoothstep(0.05, 0.3, bx); float lev = fill(max(-dy - thick, dy - thick - ridge), px * 2.0 + 0.004 * smoothstep(0.0, -thick, dy)); col = mix(col, mix(vec3(0.003, 0.012, 0.014) + vec3(0.1, 0.24, 0.22) * smoothstep(thick * 0.5, thick + ridge, dy) * (0.3 + rays * 1.5) * exp(-dd * 1.5), water * 0.5, 0.25), lev); vec2 lc = vec2(fract(p.x * 17.0) - 0.5, (dy + thick * 0.15) / (thick * 0.1 + 0.002)); col += vec3(0.32, 0.8, 0.5) * exp(-lc.x * lc.x * 40.0 - lc.y * lc.y) * lev * (0.3 + 0.7 * pow(0.5 + 0.5 * sin(p.x * 5.0 - t * 0.7), 3.0)); // The drowned one at a slant, lit only from above, its lower half lost in the murk. float fs = mix(0.16, 0.17, wide); vec2 fq = mat2(0.94, 0.34, -0.34, 0.94) * ((p - vec2(mix(0.3, 0.44, wide) * ar + 0.005 * sin(t * 0.3), wl0 - 0.04 - fs)) / fs - vec2(0.0, 0.5)) + vec2(0.0, 0.5); fq.x += 0.025 * sin(t * 0.33 + fq.y * 2.0); if (abs(fq.x - 0.05) < 0.45 && fq.y > -0.15 && fq.y < 1.25) { float fd = body(fq, t), murk = sat((0.55 - fq.y) * 1.6), lit = smoothstep(-0.015, 0.0, fd) * smoothstep(0.35, 0.95, fq.y) * 0.7; // upper edges catch the light vec3 fc = vec3(0.006, 0.02, 0.024) + vec3(0.45, 0.7, 0.62) * lit * (0.4 + 1.5 * rays) * (1.0 - murk); col = mix(col, mix(fc, water, 0.1 + 0.5 * murk), fill(fd, px / fs * (1.0 + 7.0 * murk))); } // The sea stack: slanted strata, lit ledges, greener and darker with depth. float side = step(p.x, lx), sk = p.y * 9.0 + side * 0.45, L = floor(sk), f = fract(sk), hr = h1(L + side * 7.0); float strata = noise(vec2(p.x * 10.0, p.y * 46.0)), crack = noise(vec2(p.x * 34.0, p.y * 9.0)); float ex = abs(p.x - lx - 0.01 * sin(p.y * 6.0)) - 0.008 * (crack - 0.5) - sc * (0.1 + 0.07 * smoothstep(wl0, 0.0, p.y) + 0.055 * (hr - 0.5) + 0.05 * (h1(L + 11.0 + side) - 0.5) * (f - 0.5) + 0.02 * smoothstep(0.12, 0.0, f) * (h1(L - 1.0 + side * 7.0) - hr)); float shade = 0.4 + 0.8 * smoothstep(0.55, 0.8, strata) - 0.35 * smoothstep(0.35, 0.15, strata) + 0.4 * smoothstep(0.8, 1.0, f) - 0.3 * smoothstep(0.25, 0.1, crack) + 0.6 * smoothstep(0.035, 0.0, -ex) * side; col = mix(col, mix(mix(vec3(0.1, 0.22, 0.21), vec3(0.01, 0.05, 0.035), sat(dd * 2.2)) * shade * (0.55 + rays * 1.4), water, sat(dd * 0.9) * 0.5), fill(ex, px)); // Kelp swaying. if (abs(rx) < 0.4 * sc && p.y < wl0 * 0.75) { for (int i = 0; i < 4; i++) { float fi = float(i), kt = wl0 * (0.5 + 0.08 * fi - 0.15 * step(1.5, fi)), s = sat(p.y / kt), lf = sin(p.y * 31.0 + fi * 2.0); float kd = abs(rx - (fi < 1.5 ? -0.15 - fi * 0.07 : 0.1 + fi * 0.045) * sc - 0.035 * sin(p.y * 7.0 - t * 0.5 + fi * 1.7) * s) - (0.004 + 0.009 * lf * lf) * (1.3 - s); col = mix(col, mix(vec3(0.03, 0.1, 0.06) + vec3(0.1, 0.24, 0.13) * (0.3 + rays * 2.0) * s, water, 0.2 + 0.4 * sat(0.6 - s)), fill(kd, px * 1.2) * step(p.y, kt)); } } col += vec3(0.16, 0.28, 0.26) * (1.0 + 1.5 * onSea) * exp(-dd * 60.0) * smoothstep(0.0, px * 2.0, dd); } // The meniscus, brightest under the moon and the beams; vignette. col += vec3(0.6, 0.85, 0.8) * smoothstep(px * 3.0, 0.0, abs(p.y - wl)) * (0.3 + 0.5 * exp(-pow((p.x - moon.x) / 0.15, 2.0)) + 0.7 * onSea); vec2 v = pixel / iResolution.xy - 0.5; col *= 1.0 - 0.45 * dot(v, v); color = vec4(col / (1.0 + col * 0.25), 1.0); }