Neural Nebula

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

Volumetric clouds + neural nodes + tube connections

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)

// Neural Nebula - Volumetric Clouds with Neural Pathways

float iTime = 0.0;

// Hash function
float hash(vec3 p) {
    return fract(sin(dot(p, vec3(127.1, 311.7, 74.7))) * 43758.5453);
}

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

// 3D Noise
float noise(vec3 p) {
    vec3 i = floor(p);
    vec3 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);
    
    float n = mix(
        mix(
            mix(hash(i + vec3(0,0,0)), hash(i + vec3(1,0,0)), f.x),
            mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x),
            f.y
        ),
        mix(
            mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x),
            mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x),
            f.y
        ),
        f.z
    );
    return n;
}

// fbm for clouds
float fbm(vec3 p) {
    float value = 0.0;
    float amplitude = 0.5;
    for(int i = 0; i < 5; i++) {
        value += amplitude * noise(p);
        p *= 2.0;
        amplitude *= 0.5;
    }
    return value;
}

// Rotation
mat3 rotY(float a) {
    float c = cos(a), s = sin(a);
    return mat3(c, 0, s, 0, 1, 0, -s, 0, c);
}

mat3 rotX(float a) {
    float c = cos(a), s = sin(a);
    return mat3(1, 0, 0, 0, c, -s, 0, s, c);
}

// Scene map - returns (distance, material)
vec2 map(vec3 p) {
    float d = 1e10;
    float mat = 0.0;
    
    // Neural nodes (spheres at scattered positions)
    for(int i = 0; i < 8; i++) {
        float fi = float(i);
        vec3 nodePos = vec3(
            sin(fi * 1.3 + iTime * 0.2) * 1.5,
            cos(fi * 0.9 + iTime * 0.3) * 1.2,
            sin(fi * 0.7 + iTime * 0.15) * 1.8
        );
        float nodeSize = 0.25 + 0.1 * sin(fi * 2.0 + iTime);
        float dNode = length(p - nodePos) - nodeSize;
        
        if(dNode < d) {
            d = dNode;
            mat = 1.0 + fi; // Each node different material
        }
    }
    
    // Connections between nodes (tubes)
    for(int i = 0; i < 7; i++) {
        float fi = float(i);
        vec3 p1 = vec3(
            sin(fi * 1.3 + iTime * 0.2) * 1.5,
            cos(fi * 0.9 + iTime * 0.3) * 1.2,
            sin(fi * 0.7 + iTime * 0.15) * 1.8
        );
        vec3 p2 = vec3(
            sin((fi+1.0) * 1.3 + iTime * 0.2) * 1.5,
            cos((fi+1.0) * 0.9 + iTime * 0.3) * 1.2,
            sin((fi+1.0) * 0.7 + iTime * 0.15) * 1.8
        );
        
        // Segment SDF
        vec3 pa = p - p1;
        vec3 ba = p2 - p1;
        float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
        float dTube = length(pa - ba * h) - 0.06;
        
        if(dTube < d) {
            d = dTube;
            mat = 9.0; // Tube material
        }
    }
    
    // Volumetric cloud field (soft intersection)
    float cloud = fbm(p * 0.8 + iTime * 0.1) - 0.6;
    float dCloud = cloud * 0.5; // Soft density
    
    // Blend clouds with geometry (soft union)
    d = smin(d, dCloud, 0.3);
    
    return vec2(d, mat);
}

// Smooth min
float smin(float a, float b, float k) {
    float h = max(k - abs(a - b), 0.0) / k;
    return min(a, b) - h * h * k * 0.25;
}

// Get normal
vec3 getNormal(vec3 p) {
    vec2 e = vec2(0.001, 0.0);
    return normalize(vec3(
        map(p + e.xyy).x - map(p - e.xyy).x,
        map(p + e.yxy).x - map(p - e.yxy).x,
        map(p + e.yyx).x - map(p - e.yyx).x
    ));
}

// Electric palette
vec3 electric(float t) {
    return vec3(0.1 + 0.4 * sin(t), 0.2 + 0.5 * sin(t + 1.0), 0.6 + 0.4 * sin(t + 2.0));
}

// Aurora palette
vec3 aurora(float t) {
    return vec3(0.2 + 0.3 * sin(t + 2.5), 0.5 + 0.3 * sin(t + 1.5), 0.3 + 0.4 * sin(t + 4.0));
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    
    // Camera orbit
    vec3 ro = vec3(cos(iTime * 0.15) * 4.0, 1.5 + sin(iTime * 0.1), sin(iTime * 0.15) * 4.0);
    vec3 lookAt = vec3(0.0, 0.0, 0.0);
    vec3 forward = normalize(lookAt - ro);
    vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));
    vec3 up = cross(right, forward);
    vec3 rd = normalize(forward + uv.x * right + uv.y * up);
    
    // Raymarch
    float dist = 0.0;
    vec3 hitPoint;
    float hitMat = 0.0;
    bool hit = false;
    
    for(int i = 0; i < 80; i++) {
        vec3 p = ro + rd * dist;
        vec2 dm = map(p);
        float d = dm.x;
        if(d < 0.005) {
            hit = true;
            hitPoint = p;
            hitMat = dm.y;
            break;
        }
        dist += max(d * 0.5, 0.01);
        if(dist > 15.0) break;
    }
    
    vec3 col = vec3(0.02, 0.03, 0.06); // Deep space background
    
    if(hit) {
        vec3 n = getNormal(hitPoint);
        vec3 viewDir = -rd;
        
        // Lights
        vec3 lightDir1 = normalize(vec3(0.5, 1.0, 0.3));
        vec3 lightDir2 = normalize(vec3(-0.3, 0.5, -0.5));
        
        // Material color based on type
        vec3 baseColor;
        if(hitMat < 9.0) {
            // Neural nodes - varied colors
            float hue = hitMat * 0.8 + iTime * 0.3;
            baseColor = mix(electric(hue), aurora(hue + 1.0), 0.5);
        } else {
            // Tubes - bright cyan/white
            baseColor = vec3(0.7, 0.9, 1.0);
        }
        
        // Lighting
        vec3 halfway1 = normalize(viewDir + lightDir1);
        float spec1 = pow(max(0.0, dot(n, halfway1)), 64.0);
        float diff1 = max(0.0, dot(n, lightDir1));
        
        vec3 halfway2 = normalize(viewDir + lightDir2);
        float spec2 = pow(max(0.0, dot(n, halfway2)), 32.0);
        float diff2 = max(0.0, dot(n, lightDir2));
        
        float ambient = 0.1;
        col = baseColor * (ambient + diff1 * 0.5 + diff2 * 0.3) 
            + vec3(1.0) * (spec1 * 0.6 + spec2 * 0.3);
        
        // Inner glow for nodes
        if(hitMat < 9.0) {
            col += baseColor * 0.3; // Self-illumination
        }
    }
    
    // Background stars
    float star = hash2(uv * 1000.0 + iTime * 0.01);
    if(star > 0.997) col += vec3(0.9, 0.95, 1.0) * (star - 0.997) * 300.0;
    
    // Volumetric fog overlay
    float fog = fbm(ro + rd * 5.0 + iTime * 0.1) * 0.15;
    col = mix(col, vec3(0.1, 0.15, 0.3), fog);
    
    // Vignette
    float vignette = 1.0 - length(uv) * 0.45;
    col *= vignette;
    
    // Intensity boost
    col *= 1.6;
    
    // Gamma
    col = pow(col, vec3(0.85));
    
    fragColor = vec4(clamp(col, 0.0, 1.0), 1.0);
}

void main() {
    mainImage(gl_FragColor, gl_FragCoord.xy);
}

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