Back to shaders

Shader test bench

20251023

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;

// TODO(human): Experiment with these parameters to customize the visual
// Try different values: CIRCLES (3-12), LAYERS (2-5), SPEED (0.2-0.8)
#define CIRCLES 7.0
#define LAYERS 4.0
#define SPEED 0.6

// Golden ratio - the sacred proportion
const float PHI = 1.618033988749895;

// 2D rotation matrix
mat2 rot(float a) {
    float c = cos(a);
    float s = sin(a);
    return mat2(c, -s, s, c);
}

// Flower of Life pattern - overlapping circles in sacred geometry
float flowerOfLife(vec2 uv, float radius) {
    float d = 1e10; // Start with large distance

    // Create hexagonal arrangement of circles
    for(float i = 0.0; i < CIRCLES; i++) {
        float angle = i * 6.283185 / CIRCLES;
        vec2 offset = vec2(cos(angle), sin(angle)) * radius;

        // Distance to circle edge
        float circle = abs(length(uv - offset) - radius);
        d = min(d, circle);

        // Center circle
        d = min(d, abs(length(uv) - radius));
    }

    return d;
}

// Fibonacci spiral using golden ratio
float fibonacciSpiral(vec2 uv, float t) {
    float angle = atan(uv.y, uv.x);
    float radius = length(uv);

    // Logarithmic spiral based on golden ratio
    float spiral = abs(radius - exp(angle / PHI + t));
    return spiral;
}

// Metatron's Cube - sacred geometry pattern
float metatronsCube(vec2 uv) {
    float d = 1e10;

    // Create vertices of a cube in 2D projection
    for(float i = 0.0; i < 6.0; i++) {
        float a = i * 1.0472; // 60 degrees
        vec2 p = vec2(cos(a), sin(a)) * 0.5;

        // Connect to all other points
        for(float j = i + 1.0; j < 6.0; j++) {
            float b = j * 1.0472;
            vec2 q = vec2(cos(b), sin(b)) * 0.5;

            // Line segment distance
            vec2 pa = uv - p;
            vec2 ba = q - p;
            float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
            float dist = length(pa - ba * h);
            d = min(d, dist);
        }
    }

    return d;
}

// Mandala-like pattern with symmetry
float mandala(vec2 uv, float time, float petals) {
    float angle = atan(uv.y, uv.x);
    float radius = length(uv);

    // Create petal symmetry
    float a = mod(angle, 6.283185 / petals) * petals;

    // Animate the petals opening and closing
    float petal = abs(sin(a + time) * 0.3 + 0.5 - radius);

    return petal;
}

// Vesica Piscis - sacred geometry intersection
float vesicaPiscis(vec2 uv, float offset, float radius) {
    float c1 = length(uv - vec2(offset, 0.0)) - radius;
    float c2 = length(uv + vec2(offset, 0.0)) - radius;

    // Intersection of two circles
    return max(c1, c2);
}

// Sri Yantra inspired triangular pattern
float sriYantra(vec2 uv, float time) {
    float d = 1e10;

    // Create interlocking triangles (upward and downward)
    for(float i = 0.0; i < 9.0; i++) {
        float scale = 0.3 + i * 0.08;
        float angle = time * 0.05 + i * 0.3;

        // Upward triangle
        vec2 uv1 = uv * rot(angle);
        float tri1 = abs(abs(atan(uv1.y, uv1.x) * 3.0 / 3.14159) - 1.0);
        tri1 = abs(length(uv1) * tri1 - scale);

        // Downward triangle
        vec2 uv2 = uv * rot(-angle + 3.14159);
        float tri2 = abs(abs(atan(uv2.y, uv2.x) * 3.0 / 3.14159) - 1.0);
        tri2 = abs(length(uv2) * tri2 - scale);

        d = min(d, min(tri1, tri2));
    }

    return d;
}

// Torus knot - beautiful 3D mathematical curve projected to 2D
float torusKnot(vec2 uv, float time, float p, float q) {
    float angle = atan(uv.y, uv.x);
    float radius = length(uv);

    // Parametric torus knot equations
    float t = angle * p + time;
    float knotRadius = 0.4 + 0.2 * cos(q * angle - time * 2.0);

    float d = abs(radius - knotRadius);
    return d;
}

// Concentric rings with golden ratio spacing
float goldenRings(vec2 uv, float time) {
    float r = length(uv);
    float d = 1e10;

    // Create rings spaced by golden ratio
    for(float i = 1.0; i < 8.0; i++) {
        float ringRadius = 0.15 * pow(PHI, i - 4.0);
        float ring = abs(r - ringRadius);

        // Animate ring thickness
        float thickness = 0.015 + 0.01 * sin(time * 2.0 + i);
        ring = smoothstep(thickness, thickness * 0.5, ring);

        d = max(d, ring);
    }

    return d;
}

// Platonic solid projection - dodecahedron
float dodecahedron(vec2 uv, float time) {
    float d = 1e10;

    // Pentagon symmetry (5-fold)
    float angle = atan(uv.y, uv.x);
    float sector = mod(angle, 6.283185 / 5.0) * 5.0;

    vec2 uvSym = vec2(cos(sector), sin(sector)) * length(uv);

    // Create pentagonal pattern
    for(float i = 0.0; i < 5.0; i++) {
        float a = i * 6.283185 / 5.0 + time * 0.1;
        vec2 p = vec2(cos(a), sin(a)) * 0.4;
        d = min(d, length(uvSym - p));
    }

    return d;
}

void main()
{
    // Normalize coordinates to -1 to 1, aspect ratio corrected
    vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / u_resolution.y;

    float time = u_time * SPEED;

    // Initialize final value
    float value = 0.0;

    // Breathing effect - makes the whole composition pulse
    float breath = sin(time * 0.5) * 0.15 + 1.0;

    // Layer 1: Rotating Flower of Life with breathing
    vec2 uv1 = uv * rot(time * 0.2) * breath;
    float flower = flowerOfLife(uv1, 0.3);
    flower = smoothstep(0.015, 0.008, flower);
    value += flower * 0.5;

    // Layer 2: Counter-rotating smaller flower
    vec2 uv2 = uv * rot(-time * 0.3) * 1.5;
    float flower2 = flowerOfLife(uv2, 0.2);
    flower2 = smoothstep(0.01, 0.003, flower2);
    value += flower2 * 0.35;

    // Layer 3: Multiple Fibonacci spirals at different scales
    for(float i = 0.0; i < 3.0; i++) {
        vec2 uv3 = uv * rot(time * 0.1 * (i + 1.0)) * (1.0 + i * 0.5);
        float spiral = fibonacciSpiral(uv3 * 2.0, time + i);
        spiral = smoothstep(0.08, 0.02, spiral);
        value += spiral * 0.15;
    }

    // Layer 4: Metatron's Cube rotating and scaling
    vec2 uv4 = uv * rot(time * 0.18) * (2.0 + sin(time * 0.3) * 0.3);
    float metatron = metatronsCube(uv4);
    metatron = smoothstep(0.025, 0.008, metatron);
    value += metatron * 0.4;

    // Layer 5: Animated Mandala petals
    vec2 uv5 = uv * rot(-time * 0.12);
    float mandalaPattern = mandala(uv5 * 1.5, time * 2.0, 8.0);
    mandalaPattern = smoothstep(0.1, 0.05, mandalaPattern);
    value += mandalaPattern * 0.25;

    // Layer 6: Vesica Piscis - sacred lens shape that morphs
    vec2 uv6 = uv * rot(time * 0.08);
    float offset = 0.3 + sin(time * 0.4) * 0.1;
    float vesica = abs(vesicaPiscis(uv6, offset, 0.5));
    vesica = smoothstep(0.02, 0.005, vesica);
    value += vesica * 0.3;

    // Add multiple radial pulses based on golden ratio
    float pulse1 = sin(length(uv) * PHI * 3.0 - time * 3.0) * 0.5 + 0.5;
    pulse1 = pow(pulse1, 4.0) * 0.12;

    float pulse2 = sin(length(uv) * PHI * 6.0 + time * 2.0) * 0.5 + 0.5;
    pulse2 = pow(pulse2, 3.0) * 0.08;

    value += pulse1 + pulse2;

    // Add subtle noise texture for organic feel
    float noise = fract(sin(dot(uv * 10.0, vec2(12.9898, 78.233)) + time * 0.1) * 43758.5453);
    value += noise * 0.03;

    // Create contrast and clamp
    value = clamp(value, 0.0, 1.0);

    // Enhanced contrast curve for more dramatic blacks and whites
    value = pow(value, 0.7);
    value = smoothstep(0.2, 0.8, value);

    // Black and white output with subtle vignette
    float vignette = 1.0 - length(uv) * 0.3;
    value *= vignette;

    fragColor = vec4(vec3(value), 1.0);
}