// Glasswing, 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 tri(float x) { return 1.0 - abs(2.0 * fract(x) - 1.0); } // Frame-wide values, set once in mainImage. float ar, wide, px, lake, tw; vec2 mc; // A cheap hash without sine, for the wing cells and stars. vec2 cell(vec2 p) { vec3 q = fract(p.xyx * vec3(0.1031, 0.103, 0.0973)); q += dot(q, q.yzx + 33.33); return fract((q.xx + q.yz) * q.zy); } vec3 spectrum(float x) { return 0.5 + 0.5 * cos(6.283 * (x + vec3(0.0, 0.33, 0.67))); } // Behind the glass: dusk sky, clouds, moon, faceted peaks, the old tower, the wanderer. vec3 world(vec2 p, bool clouds) { vec3 col = mix(vec3(0.76, 0.49, 0.56), vec3(0.6, 0.34, 0.54), smoothstep(0.28, 0.6, p.y)); col = mix(col, vec3(0.24, 0.16, 0.4), smoothstep(0.58, 1.15, p.y)); if (clouds) col += vec3(0.22, 0.12, 0.16) * smoothstep(0.45, 0.85, noise(vec2(p.x * 1.6 + sin(tw * 0.1) * 0.3, p.y * 13.0))) * smoothstep(0.48, 0.62, p.y) * smoothstep(1.0, 0.7, p.y); vec2 md = p - mc; float mr = length(md); col += vec3(1.0, 0.88, 0.94) * 0.09 / (1.0 + mr * 9.0); col = mix(col, vec3(1.0, 0.96, 0.92), smoothstep(0.06 + px, 0.06 - px, mr)); for (int i = 0; i < 4; i++) { float fi = float(i), k = fi / 3.0, f = p.x * (1.0 + fi * 0.5) + fi * 3.7; float h = mix(0.47, 0.29, k) + (tri(f * 0.8) * 0.62 + tri(f * 1.9 + 0.3) * 0.26 + tri(f * 4.3 + 1.1) * 0.12) * mix(0.13, 0.1, k); // Facets lit toward the moon, a rim on the crest, mist at the foot. float face = smoothstep(3.2 * px, -3.2 * px, 1.0 - 4.0 * abs(fract(f * 0.8 + (h - p.y) * 0.9 + 0.25) - 0.5)); vec3 lc = mix(vec3(0.72, 0.46, 0.61), vec3(0.27, 0.14, 0.3), pow(k, 0.8)) * mix(0.84, 1.1, face); lc += vec3(0.25, 0.16, 0.2) * exp(-max(h - p.y, 0.0) * 120.0) * face; lc = mix(lc, vec3(0.76, 0.49, 0.6), smoothstep(h - 0.03, h - 0.2, p.y) * mix(0.55, 0.28, k)); col = mix(col, lc, smoothstep(h + px, h - px, p.y)); if (i == 2) { float tx = mix(ar * 0.28, ar * 0.48, wide); float d = max(abs(p.x - tx) - (0.017 - 0.014 * p.y), p.y - 0.57); vec2 pq = p - vec2(tx + 0.026, 0.57); d = min(d, max(abs(length(pq) - 0.026) - 0.005, -min(pq.y, -pq.x))); col = mix(col, lc * 0.85, smoothstep(px, -px, d)); } } vec2 w = (p - vec2(mix(ar * 0.62, ar * 0.58, wide), lake)) / 0.042; float d = min(max(abs(w.x + w.y * 0.22) - 0.26 * (1.0 - w.y * 0.5), max(w.y - 1.0, -w.y)), length(w - vec2(-0.07, 1.12)) - 0.16); return mix(col, vec3(0.15, 0.08, 0.17), smoothstep(px, -px, d * 0.042)); } // A wing: edge distance, across-wing 0-1, span position, chord. vec4 wing(vec2 q, float root, float sweep, float width) { float lead = root + 0.02 * q.x - sweep * q.x * q.x; float span = width * sqrt(max(0.0, 1.0 - q.x * q.x * q.x)) * smoothstep(0.0, 0.12, q.x) + 0.012, a = (lead - q.y) / span; return vec4(max(max(-a, a - 1.0) * span, q.x - 1.0), a, q.x, span); } // Distance to a segment; a unit dome's normal. float segment(vec2 p, vec2 a, vec2 b) { vec2 pa = p - a, ba = b - a; return length(pa - ba * clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0)); } vec3 dome(vec2 e) { return vec3(e, sqrt(max(0.0, 1.0 - dot(e, e)))); } // Metallic thin film: violet at grazing angles to teal facing us, a glint, a pearl rim. vec3 metal(vec3 n, float film, float glint) { vec3 L = normalize(vec3(0.55, 0.35, 0.75)), c = spectrum(film); float spec = pow(max(2.0 * n.z * dot(n, L) - L.z, 0.0), glint); return c * (0.08 + 0.36 * max(dot(n, L), 0.0)) + mix(c, vec3(1.0), 0.55) * spec + vec3(0.8, 0.75, 0.9) * pow(1.0 - n.z, 3.0) * 0.45; } // The body (y toward the head): tucked legs, segmented abdomen, thorax, glossy eyes. vec4 body(vec2 q, float pu) { vec2 aq = vec2(abs(q.x), q.y), k1 = vec2(0.068, 0.1), k2 = vec2(0.085, 0.0); float lg = min(min(segment(aq, vec2(0.02, 0.07), k1), segment(aq, k1, vec2(0.04, 0.16))), min(segment(aq, vec2(0.025, 0.0), k2), segment(aq, k2, vec2(0.06, 0.1)))) - max(0.0045, pu * 0.6); // Abdomen: ten segments pinched at the joints, a narrow waist, a tapered tip. float t = (-q.y - 0.06) / 0.7, sg = fract(t * 10.0); float w = 0.03 * (1.0 - 0.42 * smoothstep(0.0, 0.2, t)) * (0.88 + 0.12 * sin(sg * 3.1416)) * sqrt(clamp((1.0 - t) * 14.0, 0.0, 1.0)); float ab = max(aq.x - w, max(-t, t - 1.0) * 0.7); // Thorax and compound eyes, blended into one normal, film and gloss. vec2 tc = (q - vec2(0.0, 0.025)) / vec2(0.062, 0.1), ec = (aq - vec2(0.034, 0.142)) / 0.046; float wt = smoothstep(pu, -pu, (length(tc) - 1.0) * 0.062), we = smoothstep(pu, -pu, (length(ec) - 1.0) * 0.046); vec3 n = dome(mix(mix(vec2(clamp(q.x / max(w, 0.001), -1.0, 1.0), 0.0), tc, wt), ec * sign(vec2(q.x, 1.0)), we)); float film = mix(mix(0.22 + 0.1 * t + 0.06 * sin(tw * 0.2 + t * 6.0), 0.3, wt), 0.36, we) + mix(0.2, 0.1, we) * n.z; vec3 c = metal(n, film, mix(mix(14.0, 10.0, wt), 40.0, we)) * mix(1.0 - 0.6 * (1.0 - smoothstep(0.0, 0.07 + pu * 9.0, min(sg, 1.0 - sg))), mix(1.0, 0.8, we), max(wt, we)); c += vec3(0.4, 0.5, 0.45) * smoothstep(0.012 + pu, 0.004, abs(aq.x * 0.9 + (q.y - 0.02) * 0.45 - 0.038)) * n.z * wt * (1.0 - we); c += vec3(0.7) * smoothstep(0.22, 0.08, length(n.xy - vec2(0.35, 0.35))) * we; float a = mix(mix(0.72 + 0.25 * n.z, 0.95, wt), 1.0, we) * max(smoothstep(pu, -pu, ab), max(wt, we)); return mix(vec4(0.2, 0.1, 0.24, smoothstep(pu, -pu, lg) * 0.85), vec4(c, 1.0), a); } vec3 scene(vec2 p) { vec3 col = world(p, true); // Early stars. vec2 sg = floor(p * 40.0), sh = cell(sg + 50.0), sf = fract(p * 40.0) - fract(sh * 7.0) * 0.6 - 0.2; col += vec3(1.0, 0.92, 0.96) * step(0.93, sh.x) * smoothstep(0.75, 0.95, p.y) * exp(-dot(sf, sf) / (px * px * 1600.0)); // The great dragonfly, right of centre, angled to the upper left. vec2 c = mix(vec2(ar * 0.5, 0.74), vec2(ar * 0.64, 0.7), wide) + vec2(sin(tw * 0.1), sin(tw * 0.2)) * vec2(0.03, 0.015); float s = mix(0.26, 0.5, wide), ang = 0.32 + 0.05 * sin(tw * 0.1), pu = px / s, flex = 0.025 * sin(tw * 0.5); vec2 q = mat2(cos(ang), -sin(ang), sin(ang), cos(ang)) * (p - c) / s, aq = vec2(abs(q.x), q.y); if (aq.x > 1.05 || abs(q.y) > 1.0) return col; vec4 fw = wing(aq, 0.08, flex - 0.03, 0.13), hw = wing(aq, -0.04, flex + 0.14, 0.16), wg = fw.x < hw.x ? fw : hw; float m = smoothstep(pu, -pu, wg.x); if (m > 0.0) { // Cells between cross-veins; long veins converge at the tip. vec2 g = vec2(wg.z * 16.0, wg.y * 4.0), id = floor(g), fr = fract(g), cid = id; float f1 = 9.0, f2 = 9.0; for (int j = -1; j <= 1; j++) for (int i = -1; i <= 1; i++) { vec2 o = vec2(float(i), float(j)), pt = o + 0.2 + 0.6 * cell(id + o + sign(q.x) * 7.0) - fr; float dd = dot(pt, pt); if (dd < f1) { f2 = f1; f1 = dd; cid = id + o; } else if (dd < f2) f2 = dd; } float aa = pu * 16.0 / max(wg.w * 4.0, 0.3), edge = sqrt(f2) - sqrt(f1); vec2 hh = cell(cid * 1.3 + sign(q.x) * 3.0); float hc = hh.x; float vein = max(smoothstep(0.06 + aa, 0.06 - aa, edge) * 0.35, smoothstep(0.012 + pu, -pu, wg.y * wg.w)); vein = max(vein, smoothstep(0.004 + pu, 0.004 - pu, abs(fract(wg.y * 3.0 + 0.5) - 0.5) * wg.w / 3.0) * 0.8 * step(0.05, wg.y)); // Each cell a faint lens: the world bends behind it, colours apart. vec2 o = ((fract(hh * 5.0) - 0.5) * 0.03 + (fr - 0.5) * vec2(0.01, 0.02)) * s; vec3 ra = world(p + o, false), film = spectrum(hc * 0.3 + wg.z * 0.8 + wg.y * 0.3 + 0.08 * sin(wg.z * 5.0 - tw * 0.5)); vec3 pane = vec3(ra.r, ra.g * 0.6 + col.g * 0.4, col.b) * (0.92 + 0.14 * hc) * mix(vec3(1.0), film, 0.12) + film * 0.03; // Cells catch the moon unevenly, each in its own slow turn. pane += mix(film, vec3(1.0), 0.6) * pow(max(sin(hc * 40.0 + tw * 0.3 + wg.z * 4.0), 0.0), 8.0) * 0.16; pane = mix(pane, vec3(1.0, 0.92, 0.96), vein); pane += spectrum(wg.y * 2.0 + 0.3) * exp(-abs(wg.y - 1.0) * wg.w * 300.0) * 0.3; col = mix(col, pane, m); } if (aq.x > 0.12) return col; vec4 b = body(q, pu); return mix(col, b.rgb + col * 0.2, b.a); } void mainImage(out vec4 color, in vec2 pixel) { vec2 uv = pixel / iResolution.xy; ar = iResolution.x / iResolution.y; px = 1.5 / iResolution.y; vec2 p = vec2(uv.x * ar, uv.y); wide = smoothstep(0.7, 1.4, ar); tw = mod(iTime, 62.8318); mc = mix(vec2(ar * 0.66, 0.86), vec2(ar * 0.83, 0.82), wide); lake = mix(0.3, 0.29, wide); float dz = lake - p.y; vec3 col; if (dz > 0.0) { // The lake: the scene mirrored a little lower, broken by ripples, glitter under the moon. float fade = smoothstep(0.0, 0.05, dz), n = noise(vec2(p.x * 2.5, 2.5 / (dz + 0.08) + tw * 0.5)); float rip = (n - 0.5) * (0.014 + dz * 0.08) * fade; vec3 refl = scene(vec2(p.x + rip, lake + dz * 1.1 + 0.012 + rip * 1.6)) * vec3(0.9, 0.82, 0.96); col = mix(vec3(0.15, 0.08, 0.19), refl, mix(0.68, 0.32, smoothstep(0.0, lake, dz))); col += vec3(0.12, 0.08, 0.12) * smoothstep(0.6, 0.9, n) * fade; col += vec3(0.3, 0.27, 0.3) * exp(-abs(p.x - mc.x + rip * 3.0) * 22.0) * smoothstep(0.55, 0.8, n) * fade; } else col = scene(p); // A soft mist band along the shore. col += vec3(0.16, 0.1, 0.15) * exp(-abs(dz + 0.004) * 45.0); // Falling motes, some prismatic. float fall = mod(iTime, 600.0); vec2 mp = p * 7.0 + vec2(sin(p.y * 3.0 + tw * 0.1) * 0.6, fall * 0.15); col += mix(vec3(0.42), spectrum(p.x * 2.0 + p.y) * 0.45, step(0.65, fract(dot(floor(mp), vec2(0.37, 0.71))))) * motes(mp, 0.14, 0.12, 3.0); col *= 1.0 - 0.2 * pow(length(uv - 0.5) * 1.2, 2.5); color = vec4(col, 1.0); }