// Verdant, 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 or root bending once: a to b to c, tapering. float limb(vec2 q, vec2 a, vec2 b, vec2 c, float r) { return min(seg(q, a, b, r), seg(q, b, c, r * 0.6)); } float crest(float x) { return 0.11 + 0.03 * sin(x * 2.3 + 1.0) + 0.01 * sin(x * 7.0); } // A forested ridge (fi 0 far .. 3 near): a rolling hill under an irregular canopy line of rounded crowns with a spire here // and there; clumps dappled in sun and cool shade, gold along the tops, sinking into valley mist and, far off, into haze. vec3 forest(vec3 col, vec2 p, float fi, float gy, float wide, float px, float mistN) { float depth = fi / 3.0, w = (0.006 + 0.007 * fi) * mix(0.75, 1.0, wide), x = p.x / w; float top = gy + 0.02 - fi * mix(0.085, 0.07, wide) + (0.015 + 0.012 * fi) * (sin(p.x * 1.6 + fi * 2.0) * 0.6 + sin(p.x * 3.7 + fi * 5.0) * 0.4); top += w * (0.5 * abs(sin(x * 1.3 + fi)) + 0.3 * abs(sin(x * 0.81 + 2.0 * fi)) + 0.2 * abs(sin(x * 2.1))); float r = h1(floor(x * 0.4) + fi * 13.0); top += step(0.7, r) * max(0.0, 1.0 - abs(fract(x * 0.4) - 0.5) * (2.6 + r)) * w * (1.8 + 1.5 * r); float d = p.y - top, dapple = noise(mat2(0.8, -0.6, 0.6, 0.8) * vec2(p.x, p.y * 1.4) / (w * 2.2) + fi * 7.0); vec3 moss = mix(vec3(0.77, 0.85, 0.65), vec3(0.5, 0.69, 0.4), depth), haze = vec3(0.96, 0.91, 0.7); vec3 c = mix(moss * mix(vec3(0.9, 0.96, 0.99), vec3(0.74, 0.88, 0.97), depth), moss, smoothstep(0.3, 0.72, dapple)); // cool shade, sunlit clumps c += vec3(0.95, 0.8, 0.42) * smoothstep(w * 0.9, 0.0, -d) * (0.18 + 0.12 * depth) * (0.6 + 0.6 * mistN); // gold on the tops c = mix(c, haze, smoothstep(0.0, 0.07 + 0.04 * fi, -d) * (0.35 + 0.35 * mistN) * (1.0 - 0.4 * depth)); // valley mist return mix(col, mix(c, haze, (1.0 - depth) * 0.4), fill(d, px)); } 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 S = min(0.77, ar * 1.3), tx = mix(0.5, 0.65, wide) * ar, gy = mix(0.48, 0.28, wide); // the tree's size, place, ground vec2 q = (p - vec2(tx, gy)) / S, ds = p - vec2(tx + 0.07 * S, gy + 0.42 * S); float r = length(ds), tree = 0.0; // Sky: cool jade overhead into warm gold at the haze line, a great bloom behind the crown. vec3 col = mix(vec3(1.0, 0.86, 0.56), vec3(0.83, 0.88, 0.66), smoothstep(gy - 0.05, gy + 0.3, p.y)); col = mix(col, vec3(0.52, 0.75, 0.72), smoothstep(gy + 0.25, 1.1, p.y)) + vec3(1.0, 0.82, 0.5) * exp(-r * 2.4) * 0.35 + vec3(1.0, 0.96, 0.82) * exp(-r * 7.0) * 0.4; // God rays fanning from the sun, sampled on the circle of directions so they have no seam. vec2 dir = ds / (r + 0.0001); float rays = smoothstep(0.42, 0.85, noise(dir * 7.0 + t * 0.012) * (0.8 + 0.2 * sin(dir.x * 37.0 - dir.y * 23.0))) * exp(-r * 1.2); float mistN = noise(vec2(p.x * 3.0 - t * 0.03, p.y * 12.0 + sin(p.x * 2.0 + t * 0.05))); // A far blue-green range lost in the haze, then the far forests. col = mix(col, vec3(0.78, 0.86, 0.72), fill(p.y - gy - 0.035 - 0.025 * sin(p.x * 2.1 + 0.5) - 0.012 * sin(p.x * 5.3), px) * 0.6); if (p.y < gy + 0.08) for (int i = 0; i < 2; i++) col = forest(col, p, float(i), gy, wide, px, mistN); // The tree's hill, a broad meadow mound in warm light. float hill = gy - 0.24 * S * (1.0 - exp(-q.x * q.x * 2.2)) + 0.003 * sin(q.x * 50.0) - p.y; if (hill > -0.02) col = mix(col, mix(vec3(0.66, 0.78, 0.47), vec3(0.82, 0.84, 0.55), smoothstep(-0.12, 0.0, -hill)) * (0.94 + 0.1 * mistN) + vec3(0.3, 0.25, 0.12) * smoothstep(0.008, 0.0, hill), fill(-hill, px)); if (abs(q.x) < 0.44 && q.y > -0.08 && q.y < 0.66) { // Roots gripping the hill, a massive gnarled trunk, great limbs splaying into the crown. float yy = max(q.y, 0.0); float td = abs(q.x - 0.015 * sin(q.y * 9.0) + 0.02 * q.y) - (0.038 + 0.055 * exp(-yy * 14.0) + 0.006 * sin(q.y * 40.0 + 1.0) + 0.004 * sin(q.y * 97.0)); td = max(td, q.y - 0.22); td = smin(td, limb(q, vec2(-0.03, 0.02), vec2(-0.1, -0.01), vec2(-0.2, -0.05), 0.022), 0.02); td = smin(td, limb(q, vec2(0.03, 0.02), vec2(0.11, -0.005), vec2(0.21, -0.048), 0.022), 0.02); td = smin(td, limb(q, vec2(-0.01, 0.01), vec2(-0.05, -0.03), vec2(-0.09, -0.07), 0.016), 0.02); td = smin(td, limb(q, vec2(0.0, 0.18), vec2(-0.12, 0.26), vec2(-0.24, 0.31), 0.028), 0.03); td = smin(td, limb(q, vec2(0.0, 0.19), vec2(-0.04, 0.3), vec2(-0.09, 0.42), 0.02), 0.03); td = smin(td, limb(q, vec2(0.01, 0.19), vec2(0.08, 0.3), vec2(0.07, 0.43), 0.02), 0.03); td = smin(td, limb(q, vec2(0.01, 0.18), vec2(0.14, 0.24), vec2(0.27, 0.29), 0.028), 0.03); td = max(td, -0.24 * (1.0 - exp(-q.x * q.x * 2.2)) - 0.012 - q.y); // roots sink into the hill float side = smoothstep(-0.04, 0.04, q.x - 0.015 * sin(q.y * 9.0) + 0.02 * q.y); vec3 bark = mix(vec3(0.36, 0.41, 0.39), vec3(0.56, 0.52, 0.38), side) * (0.6 + 0.55 * smoothstep(0.25, 0.65, noise(vec2(q.x * 80.0, q.y * 8.0 + q.x * 25.0)))); // furrowed bark bark += vec3(0.5, 0.38, 0.18) * smoothstep(0.012, 0.0, abs(td)) * side; // warm rim on the sun side col = mix(col, mix(bark, vec3(0.96, 0.91, 0.7), 0.15 + 0.1 * (1.0 - wide)), fill(td, px / S)); // The crown: layered leaf clumps from back to front, edges torn by leaf noise; hazier at the back, mossy in front, // cool in shade, glowing gold where the low sun shines through the thin edges. vec2 c = q + vec2(0.004 * sin(t * 0.5 + q.y * 5.0) * smoothstep(0.2, 0.45, q.y), 0.0); float leaf = noise(c * 30.0) * 0.45 + noise(mat2(0.8, -0.6, 0.6, 0.8) * c * 90.0) * 0.55; for (int row = 0; row < 4; row++) { float fr = float(row), n = 7.0 + 2.0 * step(0.5, fr) * step(fr, 2.5); float spread = fr < 0.5 ? 0.17 : (fr < 1.5 ? 0.26 : (fr < 2.5 ? 0.3 : 0.25)); vec3 tone = mix(vec3(0.55, 0.7, 0.56), vec3(0.5, 0.68, 0.37), fr / 3.0); for (int k = 0; k < 10; k++) { float fk = float(k), u = fk / (n - 1.0) * 2.0 - 1.0, hk = fract(fk * 0.618 + fr * 0.37); if (fk < n) { vec2 cc = vec2(u * spread + (hk - 0.5) * 0.03, 0.51 - fr * 0.06 + (0.045 - fr * 0.018) * (1.0 - u * u) + (hk - 0.5) * 0.04); // rows arch into a dome float rad = 0.058 + 0.026 * hk + 0.006 * fr; vec2 e = (c - cc) / vec2(1.25, 1.0); float d = length(e) / rad - 1.0 + (leaf - 0.5) * 0.7; vec2 nrm = e / rad; float facing = sat(0.35 + dot(nrm, vec2(0.5, 0.85))); vec3 lc = mix(tone * vec3(0.76, 0.9, 0.99), tone, sat(0.55 + 0.6 * nrm.y + 0.4 * (leaf - 0.5))); lc += vec3(1.0, 0.86, 0.45) * smoothstep(-0.4, 0.0, d) * facing * facing * (0.5 + 0.15 * fr); lc = mix(lc, vec3(0.96, 0.91, 0.7), 0.28 - fr * 0.09 + 0.1 * (1.0 - wide)); float cov = fill(d, px / S / rad * 1.5); col = mix(col, lc, cov); tree = max(tree, cov); } } } // Sun breaking through gaps near the heart of the crown. col += vec3(1.0, 0.9, 0.55) * smoothstep(0.78, 0.9, leaf) * tree * exp(-length(c - vec2(0.07, 0.42)) * 6.0) * 1.2; } // Nearer forests, in front of the hill's foot. if (p.y < gy - 0.02) for (int i = 2; i < 4; i++) col = forest(col, p, float(i), gy, wide, px, mistN); // The near meadow with grass tips, and the wanderer on it, cloak stirring. float nd = p.y - crest(p.x) - 0.007 * (1.0 - abs(fract(p.x * 110.0) * 2.0 - 1.0)) * h1(floor(p.x * 110.0)); col = mix(col, mix(vec3(0.66, 0.8, 0.46), vec3(0.6, 0.75, 0.44), smoothstep(0.1, 0.0, p.y)) * (0.93 + 0.12 * mistN) + vec3(0.25, 0.2, 0.08) * smoothstep(0.012, 0.0, -nd), fill(nd, px)); float wx = mix(0.3, 0.4, wide) * ar; vec2 w = (p - vec2(wx, crest(wx) - 0.004)) / 0.08; float fig = min(length(w - vec2(0.0, 0.86)) - 0.1, max(abs(w.x + 0.1 * (w.y - 0.8) + 0.04 * sin(t * 1.2 + w.y * 6.0) * (0.8 - w.y)) - 0.05 - 0.2 * (0.8 - w.y), max(w.y - 0.8, -w.y))); fig = min(fig, max(abs(w.x - 0.3 + w.y * 0.06) - 0.025, max(w.y - 1.1, -w.y))); col = mix(col, vec3(0.16, 0.22, 0.17) + vec3(0.32, 0.26, 0.12) * smoothstep(-0.06, 0.0, fig) * step(0.0, w.x), fill(fig, px / 0.08)); // Tall grass framing the lower corners, swaying, its tips in the light. float gx = p.x * 32.0, gc = floor(gx), hb = (0.04 + 0.08 * h1(gc)) * mix(0.55, 1.0, wide) * (smoothstep(0.3, 0.0, p.x / ar) + smoothstep(0.72, 1.0, p.x / ar)), yb = p.y / max(hb, 0.001); col = mix(col, vec3(0.47, 0.65, 0.39) + vec3(0.4, 0.32, 0.12) * smoothstep(0.6, 1.0, yb), fill((abs(fract(gx) - 0.5 - (0.25 + 0.12 * sin(t * 0.7 + gc * 0.9)) * yb * yb) - 0.32 * (1.0 - yb)) / 32.0, px) * step(yb, 1.0)); // Birds wheeling slowly around the crown, tiny against it. if (abs(q.x) < 0.46 && q.y > 0.42 && q.y < 0.72) for (int i = 0; i < 5; i++) { float fi = float(i), an = t * 0.07 + fi * 1.26; vec2 b = (p - vec2(tx + cos(an) * 0.4 * S, gy + (0.5 + 0.06 * sin(an * 2.0 + fi)) * S + 0.03 * fi * S)) / (0.006 + 0.002 * sin(an)); float flap = 0.35 * sin(t * 5.0 + fi * 2.0); col = mix(col, vec3(0.34, 0.4, 0.33), fill(abs(b.y - abs(b.x) * (0.5 + flap)) - 0.22 + abs(b.x) * 0.12, 0.25) * step(abs(b.x), 1.0) * mix(1.0 - tree, 1.0, step(0.0, sin(an)))); // behind the crown when passing round it } // God rays (not over the crown), sparse pollen, fireflies over the meadow. col += vec3(1.0, 0.9, 0.6) * rays * (1.0 - tree) * 0.3; col += vec3(1.0, 0.93, 0.62) * motes(p * 18.0 + vec2(t * 0.05, -t * 0.1), 0.12, 0.08, 1.0) * (0.3 + 0.3 * exp(-r * 2.0)); col += vec3(0.85, 1.0, 0.4) * motes(p * 26.0 + vec2(sin(t * 0.3) * 0.6, t * 0.04), 0.13, 0.08, 9.0) * (0.5 + 0.5 * sin(t * 1.3 + h2(floor(p * 26.0)) * 30.0)) * smoothstep(0.3, 0.06, p.y); vec2 v = pixel / iResolution.xy - 0.5; color = vec4(col * (1.0 - 0.28 * dot(v, v)), 1.0); }