Chromatic Plexus

GLSL shader by merrypranxter · created 2026-02-14 · 10s loop · 2 passes

Volumetric fiber web sphere with 8 independent thread families — latitudinal, longitudinal, diagonal, and spiral — each lit by a different palette. Spiky surface morphs as it rotates through three axes simultaneously.

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.  //1 degree
#define time iTime*2.*pi/10. //sin(time) loops 10 seconds
#define R iResolution.xy //shorthand
#define ar R.x/R.y //aspect ratio
#define M iMouse //shorthand
#define xm (M.xy/R) //normalized mouse
#define nm ((xm.xy-0.5)*vec2(ar,1.)+0.5) //aspect ratio correction
vec3 cs = vec3(1.,2.,3.);
mat2 r2d(float a) {
    return mat2(cos(a),sin(a),-sin(a),cos(a));
}

Buffer A (iChannel0)

// ============================================================
//  CHROMATIC PLEXUS v1.0
//  Volumetric fiber web sphere + Lisa Frank palette
//  No reserved words, compiler safe
// ============================================================

const float PI  = 3.14159265359;
const float TAU = 6.28318530718;
const float speed       = 0.18;
const float fiberSharp  = 90.0;
const float fiberCount  = 16.0;
const float brightness  = 1.9;
const float spikeAmt    = 0.18;

vec3 lfPalette(float t) {
    vec3 a = vec3(0.5, 0.3, 0.6);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.3, 0.9);
    vec3 d = vec3(0.0, 0.25, 0.6);
    return a + b * cos(TAU * (c * t + d));
}
vec3 neonPalette(float t) {
    vec3 a = vec3(0.4, 0.2, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.4);
    vec3 c = vec3(2.1, 1.5, 0.8);
    vec3 d = vec3(0.1, 0.4, 0.9);
    return a + b * cos(TAU * (c * t + d));
}
vec3 hotPalette(float t) {
    vec3 a = vec3(0.6, 0.4, 0.3);
    vec3 b = vec3(0.4, 0.5, 0.5);
    vec3 c = vec3(0.5, 1.0, 2.0);
    vec3 d = vec3(0.8, 0.2, 0.5);
    return a + b * cos(TAU * (c * t + d));
}

mat3 rotX(float a) {
    float ca = cos(a);
    float sa = sin(a);
    return mat3(1.0, 0.0, 0.0,
                0.0,  ca, -sa,
                0.0,  sa,  ca);
}
mat3 rotY(float a) {
    float ca = cos(a);
    float sa = sin(a);
    return mat3( ca, 0.0,  sa,
                0.0, 1.0, 0.0,
                -sa, 0.0,  ca);
}
mat3 rotZ(float a) {
    float ca = cos(a);
    float sa = sin(a);
    return mat3( ca, -sa, 0.0,
                 sa,  ca, 0.0,
                0.0, 0.0, 1.0);
}

// ---- Individual fiber families ----
// Each returns glow intensity for one family of great-circle threads

float fiberLat(vec3 p, float t) {
    float f = sin(p.y * fiberCount + t * 0.5);
    return exp(-f * f * fiberSharp);
}

float fiberLon(vec3 p, float t) {
    float ang = atan(p.z, p.x);
    float f   = sin(ang * fiberCount * 0.5 + t * 0.3);
    return exp(-f * f * fiberSharp);
}

float fiberDiag1(vec3 p, float t) {
    vec3  pr = rotX(PI * 0.25) * p;
    float f  = sin(pr.y * fiberCount * 0.8 + pr.x * fiberCount * 0.3 - t * 0.4);
    return exp(-f * f * fiberSharp);
}

float fiberDiag2(vec3 p, float t) {
    vec3  pr = rotZ(PI * 0.33) * p;
    float f  = sin(pr.y * fiberCount * 0.7 - pr.z * fiberCount * 0.4 + t * 0.2);
    return exp(-f * f * fiberSharp);
}

float fiberSpiral(vec3 p, float t) {
    float ang    = atan(p.z, p.x);
    float spiral = sin(p.y * fiberCount * 0.6 + ang * 4.0 - t * 0.6);
    return exp(-spiral * spiral * fiberSharp * 0.8);
}

float fiberDiag3(vec3 p, float t) {
    vec3  pr = rotX(PI * 0.5) * rotY(PI * 0.25) * p;
    float ang = atan(pr.z, pr.x);
    float f   = sin(ang * fiberCount * 0.4 + pr.y * fiberCount * 0.5 + t * 0.35);
    return exp(-f * f * fiberSharp);
}

float fiberDiag4(vec3 p, float t) {
    vec3  pr = rotY(PI * 0.5) * rotZ(PI * 0.2) * p;
    float f  = sin(pr.x * fiberCount * 0.9 + pr.z * fiberCount * 0.2 - t * 0.25);
    return exp(-f * f * fiberSharp);
}

float fiberSpiral2(vec3 p, float t) {
    vec3  pr  = rotY(PI * 0.5) * p;
    float ang = atan(pr.z, pr.x);
    float f   = sin(pr.y * fiberCount * 0.5 + ang * 6.0 + t * 0.4);
    return exp(-f * f * fiberSharp * 0.6);
}

// ---- Sphere surface spikes (displacement) ----
float spikeField(vec3 pn, float t) {
    float s1 = sin(pn.x * 8.0 + t * 0.7) * sin(pn.y * 7.0 - t * 0.5) * sin(pn.z * 9.0 + t * 0.3);
    float s2 = sin(pn.x * 13.0 - t * 0.4) * sin(pn.z * 11.0 + t * 0.6);
    return max(0.0, s1 * 0.6 + s2 * 0.4);
}

void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2  uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    float t  = iTime * speed;

    vec3 ro = vec3(0.0, 0.0, -3.2);
    vec3 rd = normalize(vec3(uv, 1.4));

    // Sphere-ray intersection
    float sphereR = 1.15;
    float b       = dot(ro, rd);
    float c       = dot(ro, ro) - sphereR * sphereR * 1.6;
    float disc    = b * b - c;

    vec3 col = vec3(0.01, 0.005, 0.02);

    if(disc > 0.0) {
        float sqD    = sqrt(disc);
        float tNear  = max(-b - sqD, 0.0);
        float tFar   = -b + sqD;

        if(tFar > 0.0) {
            float tRange  = tFar - tNear;
            float stepSz  = tRange / 80.0;

            // Slow rotation
            mat3 rot = rotY(t * 0.35) * rotX(t * 0.22) * rotZ(t * 0.13);

            float totalW  = 0.0;
            vec3  colAcc  = vec3(0.0);

            for(int i = 0; i < 80; i++) {
                float fi = float(i);
                float td = tNear + fi * stepSz;
                vec3  p  = ro + rd * td;
                vec3  pr = rot * p;

                float plen = length(pr);
                vec3  pn   = pr / max(plen, 0.0001);

                // Spiky shell radius
                float spike  = spikeField(pn, t);
                float shellR = sphereR * (1.0 + spike * spikeAmt);

                // Soft shell weight — concentrated near surface
                float distToShell = abs(plen - shellR);
                float shellW = exp(-distToShell * distToShell * 18.0);

                // Also allow interior web
                float interiorW = clamp(1.0 - plen / sphereR, 0.0, 1.0);
                interiorW = interiorW * interiorW * 0.4;

                float posW = shellW + interiorW;

                // All fiber families
                float f1 = fiberLat(pn,     t);
                float f2 = fiberLon(pn,     t);
                float f3 = fiberDiag1(pn,   t);
                float f4 = fiberDiag2(pn,   t);
                float f5 = fiberSpiral(pn,  t);
                float f6 = fiberDiag3(pn,   t);
                float f7 = fiberDiag4(pn,   t);
                float f8 = fiberSpiral2(pn, t);

                // Color each family differently
                float ang     = atan(pn.z, pn.x);
                float posPhase = pn.y * 0.5 + ang / TAU;

                vec3 c1 = lfPalette(posPhase + 0.0)  * f1;
                vec3 c2 = neonPalette(posPhase + 0.15) * f2;
                vec3 c3 = lfPalette(posPhase + 0.3)  * f3;
                vec3 c4 = hotPalette(posPhase + 0.45) * f4;
                vec3 c5 = neonPalette(posPhase + 0.6) * f5;
                vec3 c6 = lfPalette(posPhase + 0.75) * f6;
                vec3 c7 = hotPalette(posPhase + 0.9)  * f7;
                vec3 c8 = neonPalette(posPhase + 1.05) * f8;

                float totalFiber = f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8;
                vec3  fiberCol   = c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8;

                float contrib = totalFiber * posW * stepSz;
                colAcc  += fiberCol * posW * stepSz;
                totalW  += contrib;
            }

            float alpha  = clamp(totalW * 0.25, 0.0, 1.0);
            vec3  fibCol = colAcc / max(totalW, 0.0001);
            col = mix(col, fibCol, alpha);
            col += fibCol * alpha * alpha * 1.5;
        }
    }

    // Outer halo
    float haloDist = length(uv);
    float halo     = exp(-haloDist * 3.0) * 0.12;
    col += lfPalette(t * 0.08) * halo;

    // Vignette
    col *= 1.0 - dot(uv, uv) * 0.35;

    col = pow(clamp(col * brightness, 0.0, 1.0), vec3(0.8));
    col *= col * 1.4;

    fragColor = vec4(col, 1.0);
}

Image

Not used

More shaders by merrypranxter

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

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

Account

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