Back to shaders

Shader test bench

20251218

glsl-daily-practice generative glsl runnable fragment MIT
Source
runnable fragment

Complete GLSL fragment shader. Stronghold runs it directly when the browser can compile it.

Code

precision mediump float;
#define fragColor gl_FragColor

uniform float u_time;
uniform vec2  u_resolution;

#define PI 3.14159265359
#define TAU 6.28318530718
#define PHI 1.61803398875

// ============ UTILITIES ============

float hash(vec2 p) {
    vec3 p3 = fract(vec3(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

float noise(vec2 p) {
    vec2 i = floor(p);
    vec2 f = fract(p);
    f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
    return mix(
        mix(hash(i), hash(i + vec2(1, 0)), f.x),
        mix(hash(i + vec2(0, 1)), hash(i + vec2(1, 1)), f.x),
        f.y
    );
}

float fbm(vec2 p) {
    float v = 0.0, a = 0.5;
    mat2 rot = mat2(cos(0.37), sin(0.37), -sin(0.37), cos(0.37));
    for (int i = 0; i < 6; i++) {
        v += a * noise(p);
        p = rot * p * 2.0 + 100.0;
        a *= 0.5;
    }
    return v;
}

// Smooth ring with glow (reduced glow for clarity)
float ring(vec2 p, float r, float w, float glow) {
    float d = abs(length(p) - r);
    float core = smoothstep(w, 0.0, d);
    float glowEffect = exp(-d * glow) * 0.2;
    return core + glowEffect;
}

// Line with glow (reduced glow for clarity)
float line(vec2 p, vec2 a, vec2 b, float w, float glow) {
    vec2 pa = p - a, ba = b - a;
    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    float d = length(pa - ba * h);
    float core = smoothstep(w, 0.0, d);
    float glowEffect = exp(-d * glow) * 0.12;
    return core + glowEffect;
}

// Soft dot/star (reduced intensity)
float star(vec2 p, float r) {
    float d = length(p);
    return exp(-d * r) * 0.6;
}

// ============ SACRED GEOMETRY ============

// Complete Flower of Life (61 circles)
float flowerOfLifeFull(vec2 p, float r, float t) {
    float d = 0.0;
    float w = 0.004;
    float g = 40.0;

    // Layer 0: Center
    d += ring(p, r, w, g);

    // Layer 1: 6 circles
    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + t * 0.05;
        d += ring(p - vec2(cos(a), sin(a)) * r, r, w, g);
    }

    // Layer 2: 12 circles
    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + t * 0.05;
        d += ring(p - vec2(cos(a), sin(a)) * r * 2.0, r, w, g);
    }
    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + PI/6.0 + t * 0.05;
        d += ring(p - vec2(cos(a), sin(a)) * r * 1.732, r, w, g);
    }

    // Layer 3: 18 circles
    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + t * 0.05;
        d += ring(p - vec2(cos(a), sin(a)) * r * 3.0, r, w, g);
    }
    for (int i = 0; i < 12; i++) {
        float a = float(i) * TAU / 12.0 + PI/12.0 + t * 0.05;
        float dist = (mod(float(i), 2.0) == 0.0) ? 2.646 : 2.646;
        d += ring(p - vec2(cos(a), sin(a)) * r * dist, r, w, g);
    }

    // Outer boundary circles
    d += ring(p, r * 3.0, w * 0.5, g * 0.5) * 0.5;
    d += ring(p, r * 3.5, w * 0.3, g * 0.3) * 0.3;

    return clamp(d, 0.0, 1.0);
}

// Metatron's Cube with all platonic solid projections
float metatronComplete(vec2 p, float r, float t) {
    float d = 0.0;
    float w = 0.003;
    float g = 60.0;

    // 13 spheres of fruit of life
    vec2 pts[13];
    pts[0] = vec2(0.0);

    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + t * 0.08;
        pts[i + 1] = vec2(cos(a), sin(a)) * r * 0.33;
    }
    for (int i = 0; i < 6; i++) {
        float a = float(i) * TAU / 6.0 + PI/6.0 + t * 0.08;
        pts[i + 7] = vec2(cos(a), sin(a)) * r * 0.58;
    }

    // Draw circles at each point (reduced center glow)
    for (int i = 0; i < 13; i++) {
        d += ring(p - pts[i], r * 0.12, w, g) * 0.7;
        d += star(p - pts[i], 120.0) * 0.1; // subtle center glow
    }

    // Connect ALL points (78 lines) - this reveals platonic solids
    for (int i = 0; i < 13; i++) {
        for (int j = i + 1; j < 13; j++) {
            float fade = sin(t * 0.3 + float(i + j) * 0.2) * 0.3 + 0.7;
            d += line(p, pts[i], pts[j], w * 0.4, g * 0.8) * 0.25 * fade;
        }
    }

    return clamp(d, 0.0, 1.0);
}

// Sri Yantra - 9 interlocking triangles
float sriYantraComplete(vec2 p, float r, float t) {
    float d = 0.0;
    float w = 0.003;
    float g = 50.0;

    // Bindu (center point) - subtle
    d += star(p, 150.0) * 0.2;

    // 4 upward triangles (Shiva - masculine)
    float sizes[4] = float[4](0.95, 0.65, 0.42, 0.2);
    for (int i = 0; i < 4; i++) {
        float s = r * sizes[i];
        float rot = sin(t * 0.1) * 0.02;
        mat2 m = mat2(cos(rot), -sin(rot), sin(rot), cos(rot));

        vec2 p1 = m * vec2(0.0, s);
        vec2 p2 = m * vec2(-s * 0.866, -s * 0.5);
        vec2 p3 = m * vec2(s * 0.866, -s * 0.5);

        d += line(p, p1, p2, w, g);
        d += line(p, p2, p3, w, g);
        d += line(p, p3, p1, w, g);
    }

    // 5 downward triangles (Shakti - feminine)
    float sizesDown[5] = float[5](0.85, 0.55, 0.35, 0.25, 0.1);
    for (int i = 0; i < 5; i++) {
        float s = r * sizesDown[i];
        float rot = -sin(t * 0.1) * 0.02;
        mat2 m = mat2(cos(rot), -sin(rot), sin(rot), cos(rot));

        vec2 p1 = m * vec2(0.0, -s * 0.9);
        vec2 p2 = m * vec2(-s * 0.866, s * 0.5);
        vec2 p3 = m * vec2(s * 0.866, s * 0.5);

        d += line(p, p1, p2, w, g);
        d += line(p, p2, p3, w, g);
        d += line(p, p3, p1, w, g);
    }

    // Lotus petals (16 outer, 8 inner)
    for (int i = 0; i < 16; i++) {
        float a = float(i) * TAU / 16.0 + t * 0.02;
        float a2 = float(i + 1) * TAU / 16.0 + t * 0.02;
        vec2 outer1 = vec2(cos(a), sin(a)) * r * 1.15;
        vec2 outer2 = vec2(cos(a2), sin(a2)) * r * 1.15;
        vec2 inner = vec2(cos((a + a2) * 0.5), sin((a + a2) * 0.5)) * r * 1.0;
        d += line(p, outer1, inner, w * 0.6, g * 0.6) * 0.4;
        d += line(p, outer2, inner, w * 0.6, g * 0.6) * 0.4;
    }

    for (int i = 0; i < 8; i++) {
        float a = float(i) * TAU / 8.0 + PI/8.0 + t * 0.02;
        float a2 = float(i + 1) * TAU / 8.0 + PI/8.0 + t * 0.02;
        vec2 outer1 = vec2(cos(a), sin(a)) * r * 1.0;
        vec2 outer2 = vec2(cos(a2), sin(a2)) * r * 1.0;
        vec2 inner = vec2(cos((a + a2) * 0.5), sin((a + a2) * 0.5)) * r * 0.92;
        d += line(p, outer1, inner, w * 0.5, g * 0.5) * 0.3;
        d += line(p, outer2, inner, w * 0.5, g * 0.5) * 0.3;
    }

    // Enclosing circles
    d += ring(p, r * 1.2, w, g * 0.5) * 0.5;
    d += ring(p, r * 1.25, w * 0.5, g * 0.3) * 0.3;

    return clamp(d, 0.0, 1.0);
}

// Golden Ratio Spiral with Fibonacci
float goldenSpiralFib(vec2 p, float t) {
    float d = 0.0;

    float angle = atan(p.y, p.x);
    float radius = length(p);

    // Multiple golden spirals
    for (int j = 0; j < 4; j++) {
        float offset = float(j) * PI * 0.5;
        for (float i = -20.0; i < 20.0; i += 0.1) {
            float a = i + t * 0.2 + offset;
            float r = 0.01 * pow(PHI, a / PI);
            if (r > 0.01 && r < 1.0) {
                vec2 sp = vec2(cos(a), sin(a)) * r;
                d += exp(-length(p - sp) * 150.0) * 0.15;
            }
        }
    }

    // Fibonacci rectangles overlay
    float rectSize = 0.02;
    for (int i = 0; i < 8; i++) {
        rectSize *= PHI;
    }

    return clamp(d, 0.0, 1.0);
}

// Torus Yantra / Tube Torus projection (subtle)
float torusYantra(vec2 p, float t) {
    float d = 0.0;

    int num = 36;
    for (int i = 0; i < num; i++) {
        float a = float(i) * TAU / float(num);
        float r = 0.35 + sin(a * 6.0 + t) * 0.1;
        vec2 center = vec2(cos(a), sin(a)) * 0.25;
        d += ring(p - center, r, 0.002, 60.0) * 0.15;
    }

    return clamp(d, 0.0, 1.0);
}

// Cosmic particles / stardust
float stardust(vec2 p, float t) {
    float d = 0.0;

    for (int i = 0; i < 50; i++) {
        float fi = float(i);
        vec2 pos = vec2(
            sin(fi * 127.1 + t * 0.1) * 0.8,
            cos(fi * 311.7 + t * 0.12) * 0.8
        ) * hash(vec2(fi, fi * 0.7));

        float brightness = sin(t * 2.0 + fi) * 0.5 + 0.5;
        d += star(p - pos, 120.0) * brightness * 0.15;
    }

    return d;
}

// Mandala rings
float mandalaRings(vec2 p, float t) {
    float d = 0.0;
    float a = atan(p.y, p.x);
    float r = length(p);

    // Petal patterns at different radii
    for (int i = 1; i < 6; i++) {
        float ri = float(i) * 0.12;
        float petals = float(i + 5) * 2.0;
        float wave = sin(a * petals + t * (0.5 - float(i) * 0.1)) * 0.5 + 0.5;
        float ringMask = exp(-abs(r - ri) * 30.0);
        d += wave * ringMask * 0.4;
    }

    return d;
}

void main()
{
    vec2 uv = vUV.st;
    vec2 c = uv - 0.5;
    float t = u_time;

    float aspect = u_resolution.x / u_resolution.y;
    vec2 p = c;
    p.x *= aspect;

    // ============ LAYER COMPOSITION ============

    // Background: subtle cosmic dust
    float bg = fbm(uv * 5.0 + t * 0.02) * 0.06;
    bg += stardust(p, t) * 0.3;

    // Layer 1: Mandala rings (outermost)
    float mandala = mandalaRings(p, t);

    // Layer 2: Golden spiral (background geometry)
    float spiral = goldenSpiralFib(p, t);

    // Layer 3: Flower of Life
    float flower = flowerOfLifeFull(p * 2.8, 0.1, t);

    // Layer 4: Sri Yantra (overlaid)
    float yantra = sriYantraComplete(p * 1.5, 0.45, t);

    // Layer 5: Metatron's Cube (center focus)
    float metatron = metatronComplete(p * 1.2, 0.7, t);

    // Layer 6: Torus energy field
    float torus = torusYantra(p * 1.5, t * 0.5);

    // ============ BLENDING ============

    float pattern = bg;
    pattern += mandala * 0.3;
    pattern += spiral * 0.4;
    pattern = max(pattern, flower * 0.7);
    pattern = max(pattern, yantra * 0.85);
    pattern = max(pattern, metatron * 0.9);
    pattern += torus * 0.2;

    // ============ POST PROCESSING ============

    // Breathing pulse (subtle)
    float breath = sin(t * 0.4) * 0.05 + 0.95;
    pattern *= breath;

    // Gentle bloom (reduced)
    float bloom = pattern;
    bloom = pow(bloom, 0.7) * 0.15;
    pattern += bloom;

    // Contrast - preserve detail in bright areas
    pattern = smoothstep(0.08, 1.1, pattern);

    // Film grain (subtle)
    float grain = hash(uv * 1000.0 + t) * 0.012;
    pattern += grain;

    // Radial gradient vignette
    float vig = 1.0 - pow(length(c) * 1.2, 2.0);
    vig = smoothstep(-0.1, 1.0, vig);

    // Center glow - much softer, doesn't overpower geometry
    float centerGlow = exp(-length(p) * 5.0) * 0.05;
    pattern += centerGlow;

    // Prevent overexposure in center - soft clamp
    pattern = pattern / (pattern + 0.3) * 1.3;

    // Final composition
    float final = pattern * vig;
    final = clamp(final, 0.0, 1.0);

    // Output
    fragColor = vec4(vec3(final), 1.0);
}