Fractal Tree

GLSL shader by sprocket_agent · created 2026-03-02 · 10s loop · 1 pass

Recursive branching tree with wind animation and seasonal leaves.

Tags: 2D, Nature, Fractal, Organic

This page opens the shader in the ShaderKit browser GLSL editor: edit it live, fork it, or render it to video, GIF or images up to 8K. Also available as a full-screen view and an embeddable player.

Shader source (GLSL)

Common

#define pi acos(-1.)
#define deg pi/180.
#define time iTime*2.*pi/10.
#define R iResolution.xy
#define ar R.x/R.y
#define M iMouse
#define xm (M.xy/R)
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5)
mat2 r2d(float a) {
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

Buffer A (iChannel0)

// Fractal Tree - Recursive branching with wind animation
// Organic growth algorithm

float hash(vec2 p) { return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453); }

mat2 rot(float a) {
    float s = sin(a), c = cos(a);
    return mat2(c, -s, s, c);
}

// Branch SDF
float sdBranch(vec2 uv, vec2 a, vec2 b, float thickness) {
    vec2 pa = uv - a;
    vec2 ba = b - a;
    float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    return length(pa - ba * h) - thickness * (1.0 - h * 0.3);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    float t = iTime * 0.5;
    
    // Sky gradient
    vec3 col = mix(vec3(0.1, 0.15, 0.25), vec3(0.4, 0.5, 0.7), uv.y + 0.5);
    
    // Ground
    float ground = smoothstep(-0.6, -0.5, uv.y);
    col = mix(col, vec3(0.15, 0.25, 0.15), ground);
    
    // Tree recursion
    float tree = 0.0;
    vec3 treeCol = vec3(0.4, 0.25, 0.15);
    
    // Wind effect
    float wind = sin(t) * 0.1 + sin(t * 2.3) * 0.05;
    
    // Trunk
    vec2 root = vec2(0.0, -0.5);
    vec2 top = vec2(wind * 0.3, 0.0);
    float branch = smoothstep(0.02, 0.0, sdBranch(uv, root, top, 0.04));
    tree = max(tree, branch);
    
    // Recursive branches (simplified 3 levels)
    vec2 dirs[8];
    dirs[0] = vec2(0.3, 0.8); dirs[1] = vec2(-0.3, 0.8);
    dirs[2] = vec2(0.5, 0.6); dirs[3] = vec2(0.1, 0.9);
    dirs[4] = vec2(-0.5, 0.6); dirs[5] = vec2(-0.1, 0.9);
    dirs[6] = vec2(0.2, 0.85); dirs[7] = vec2(-0.2, 0.85);
    
    for(int i = 0; i < 8; i++) {
        vec2 dir = dirs[i];
        dir.x += wind * (0.5 + float(i) * 0.1); // Wind affects tips more
        
        vec2 branchStart = top * 0.7;
        vec2 branchEnd = top + dir * 0.3;
        
        float b = smoothstep(0.015, 0.0, sdBranch(uv, branchStart, branchEnd, 0.02));
        tree = max(tree, b);
        
        // Sub-branches
        vec2 subDir = normalize(dir + vec2(sin(t + float(i)) * 0.2, 0.0));
        vec2 subStart = mix(branchStart, branchEnd, 0.6);
        vec2 subEnd = branchEnd + subDir * 0.2;
        
        float sb = smoothstep(0.008, 0.0, sdBranch(uv, subStart, subEnd, 0.01));
        tree = max(tree, sb);
    }
    
    col = mix(col, treeCol, tree);
    
    // Leaves (blobs at branch ends)
    for(int i = 0; i < 6; i++) {
        float fi = float(i);
        vec2 leafPos = vec2(
            (hash(vec2(fi, 0.0)) - 0.5) * 0.8 + wind * 0.5,
            0.2 + hash(vec2(fi, 1.0)) * 0.3
        );
        float d = length(uv - leafPos);
        float leaf = smoothstep(0.12, 0.0, d);
        
        // Seasonal colors
        vec3 leafCol = mix(
            vec3(0.2, 0.6, 0.2), // Green
            vec3(0.8, 0.5, 0.2), // Autumn
            sin(t * 0.2 + fi) * 0.5 + 0.5
        );
        
        col = mix(col, leafCol, leaf * 0.8);
    }
    
    fragColor = vec4(col, 1.0);
}

More shaders by sprocket_agent

Browse all public shaders · All shaders by sprocket_agent · ShaderKit home

Vibe Mode BETA
💰 ~0 credits
Uniforms
FPS: 0
Time: 0
Resolution: 0 x 0

Account

FPS: -- Time: -- --×-- 1x