Orb 1

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

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)

// "Lisa Frank's Hyper-Gyroid"
// Concept: Maximalist Gyroid Mandala with Pulse Dynamics & Acid Coloring
// Vibe: Boom Boom Pop Power.

// --- 🎛️ CONTROLS ---
#define CAMERA_DIST 8.0      // Distance (Keep it 8-10 to see the whole orb)
#define SYMMETRY 6.0         // 6-fold snowflake symmetry (Classic kaleidoscope)
#define FLOW_SPEED 1.5       // How fast the liquid flows
#define PULSE_SPEED 4.0      // The "Boom Boom" Heartbeat speed
#define GLITTER_AMT 0.8      // Holographic sparkle intensity

// --- 🦄 ACID PALETTE (Lisa Frank Mode) ---
// High saturation, shifting between Pink, Cyan, Yellow, Violet
vec3 acidPalette(float t) {
    vec3 a = vec3(0.5, 0.5, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.0, 1.0);
    vec3 d = vec3(0.3, 0.20, 0.20); // Shifted for Pinks/Purples
    
    vec3 col = a + b * cos(6.28318 * (c * t + d));
    // Boost saturation to make it "Pop"
    return pow(col, vec3(0.6)); 
}

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

// Smooth Min
float smin(float a, float b, float k) {
    float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
    return mix(b, a, h) - k * h * (1.0 - h);
}

// --- 💎 GEOMETRY ---

float sdGyroid(vec3 p, float scale, float thickness, float bias) {
    p *= scale;
    float g = dot(sin(p), cos(p.yzx));
    return abs(g - bias) / scale - thickness;
}

float map(vec3 p) {
    vec3 p0 = p;
    
    // 1. DYNAMIC PULSE (The "Boom Boom")
    // We warp the space based on a heartbeat rhythm
    float beat = sin(iTime * PULSE_SPEED) * 0.05;
    
    // 2. MANDALA SYMMETRY
    float angle = atan(p.z, p.x);
    float radius = length(p.xz);
    float sector = 6.28318 / SYMMETRY;
    angle = abs(mod(angle, sector) - sector * 0.5);
    p.xz = vec2(cos(angle), sin(angle)) * radius;
    
    // 3. LIQUID FLOW (Turbulence)
    // Rotate and push Z to make it look like flowing icing
    p.xy *= rot(p.z * 0.3 + iTime * 0.5);
    p.z += iTime * FLOW_SPEED; 
    
    // 4. THE SHAPES
    
    // The Gyroid Lattice (Thick and flowing)
    // We modify thickness with the 'beat' to make it pump
    float field = sdGyroid(p, 2.5, 0.08 + beat, 0.0);
    
    // The Container Sphere
    float sphereDist = length(p0) - 4.2;
    
    // Intersection: Cut the gyroid into a ball
    float d = max(field, sphereDist);
    
    // Add Central Core (The Moon/Heart)
    float core = length(p0) - 1.2 + beat * 2.0;
    d = smin(d, core, 0.5);
    
    return d;
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    
    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
    vec3 ro = vec3(0.0, 0.0, -CAMERA_DIST);
    vec3 rd = normalize(vec3(uv, 1.0));
    
    // Rotate camera slightly for dynamism
    ro.xy *= rot(iTime * 0.2);
    rd.xy *= rot(iTime * 0.2);

    float t = 0.0;
    float d = 0.0;
    vec3 glow = vec3(0.0);
    
    // Raymarching
    for(int i = 0; i < 70; i++) {
        vec3 p = ro + rd * t;
        d = map(p);
        
        // --- THE POP POWER GLOW ---
        // We make the glow incredibly intense near the surface
        float proximity = 1.0 / (abs(d) * 15.0 + 1.0);
        
        // Interference Pattern (Rainbow Rings)
        // High frequency sine waves for that "Oil Slick" look
        float interference = sin(d * 50.0 - iTime * 5.0);
        
        // Color Selection
        // We map the position 'p' to the acid palette
        vec3 acid = acidPalette(length(p) * 0.3 - iTime * 0.4);
        
        // Sparkle/Glitter Logic
        // High frequency noise based on view direction
        float sparkle = sin(dot(rd, p) * 100.0);
        if (sparkle > 0.95) acid += vec3(1.0); // White sparkles
        
        glow += acid * proximity * (0.8 + 0.3 * interference) * 0.05;
        
        if (abs(d) < 0.001 || t > 20.0) break;
        t += d * 0.7; // Step forward
    }
    
    vec3 col = vec3(0.0);
    col += glow;
    
    // --- POST PROCESSING: MAXIMALISM ---
    
    // 1. Contrast Curve (Make darks dark, brights neon)
    col = pow(col, vec3(1.2));
    
    // 2. Saturation Boost
    vec3 luminance = vec3(dot(col, vec3(0.299, 0.587, 0.114)));
    col = mix(luminance, col, 1.4); 
    
    // 3. Purple Background Haze (instead of black void)
    float bgMask = smoothstep(3.5, 5.0, length(uv * 4.0));
    col += vec3(0.2, 0.0, 0.3) * bgMask; // Deep purple edges

    fragColor = vec4(col, 1.0);
}

Buffer B (iChannel1)

// "The Lisa Frank Collider"
// Two infinite math fields colliding in a container sphere.
// Channel 1: Pink/Gold Slime (Slow, Organic)
// Channel 2: Cyan/Violet Crystal (Fast, Sharp)
// Interaction: Liquid blending with a white-hot collision line.

// --- 🎛️ MIXING CONSOLE ---
#define CAMERA_DIST 9.0
#define CORE_SIZE 4.2       // Size of the container ball
#define BLEND_SMOOTH 0.4    // How much they melt into each other
#define COLLISION_GLOW 2.0  // Brightness where they touch

// --- 🎨 PALETTE 1: THE HOST (Warm/Acid) ---
vec3 paletteA(float t) {
    vec3 a = vec3(0.5, 0.5, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.0, 1.0);
    vec3 d = vec3(0.3, 0.20, 0.20); // Pinks & Yellows
    return pow(a + b * cos(6.28318 * (c * t + d)), vec3(0.5));
}

// --- 🎨 PALETTE 2: THE INTRUDER (Cool/Electric) ---
vec3 paletteB(float t) {
    vec3 a = vec3(0.5, 0.5, 0.5);
    vec3 b = vec3(0.5, 0.5, 0.5);
    vec3 c = vec3(1.0, 1.0, 1.0);
    vec3 d = vec3(0.0, 0.10, 0.20); // Cyans & Blues
    return pow(a + b * cos(6.28318 * (c * t + d)), vec3(0.5));
}

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

// GYROID FUNCTION
float sdGyroid(vec3 p, float scale, float thickness, float bias) {
    p *= scale;
    float g = dot(sin(p), cos(p.yzx));
    return abs(g - bias) / scale - thickness;
}

// --- 🧬 THE DUAL PHYSICS ENGINE ---
// Returns: vec2( distance, material_mix_ratio )
vec2 map(vec3 p) {
    vec3 p0 = p;
    
    // Containment Sphere
    float sphere = length(p) - CORE_SIZE;
    
    // --- CHANNEL 1: THE HOST ---
    // Slow, thick, pulsing
    vec3 p1 = p;
    p1.xy *= rot(iTime * 0.2); // Spin Left
    float beat = sin(iTime * 2.0) * 0.05;
    float g1 = sdGyroid(p1, 2.5, 0.1 + beat, 0.0);
    
    // --- CHANNEL 2: THE INTRUDER ---
    // Fast, sharp, offset
    vec3 p2 = p;
    p2.yz *= rot(-iTime * 0.5); // Spin Right (Inverse axis)
    p2.x += iTime; // Flow through
    float g2 = sdGyroid(p2, 4.0, 0.03, 0.0);
    
    // --- THE INTERACTION (Liquid Blend) ---
    // smin blends the distances
    float k = BLEND_SMOOTH;
    float h = clamp( 0.5 + 0.5 * (g2 - g1) / k, 0.0, 1.0 );
    float mixedDist = mix( g2, g1, h ) - k * h * (1.0 - h);
    
    // Crop to sphere
    float d = max(mixedDist, sphere);
    
    // Return distance AND the mixing factor 'h'
    // h = 0.0 means Pure Channel 2
    // h = 1.0 means Pure Channel 1
    // h = 0.5 means THE COLLISION ZONE
    return vec2(d, h);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    
    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
    vec3 ro = vec3(0.0, 0.0, -CAMERA_DIST);
    vec3 rd = normalize(vec3(uv, 1.0));
    
    // Camera Orbit
    ro.xz *= rot(iTime * 0.1);
    rd.xz *= rot(iTime * 0.1);

    float t = 0.0;
    vec2 d = vec2(0.0);
    vec3 finalCol = vec3(0.0);
    
    // Raymarching
    for(int i = 0; i < 80; i++) {
        vec3 p = ro + rd * t;
        d = map(p); // Get distance and material mix
        
        float dist = d.x;
        float material = d.y; // 0.0 to 1.0 mix
        
        // --- DUAL CHANNEL COLORING ---
        // Calculate closeness to surface
        float proximity = 1.0 / (abs(dist) * 20.0 + 1.0);
        
        // Channel 1 Color
        vec3 col1 = paletteA(length(p)*0.2 - iTime*0.2);
        // Channel 2 Color
        vec3 col2 = paletteB(length(p)*0.4 + iTime*0.5);
        
        // Mix them based on the physics blend 'd.y'
        vec3 mixedCol = mix(col2, col1, material);
        
        // --- INTERACTION SPARK (The "Third" Color) ---
        // If material is near 0.5, it means the two fields are fighting.
        // We add a white hot glow at this boundary.
        float interaction = 1.0 - abs(material * 2.0 - 1.0); // 1.0 at center mix
        interaction = pow(interaction, 6.0); // Sharpen the line
        
        // Add the spark to the mix
        mixedCol += vec3(1.0, 1.0, 0.8) * interaction * COLLISION_GLOW;
        
        // Add to total light
        finalCol += mixedCol * proximity * 0.05;
        
        if (abs(dist) < 0.001 || t > 20.0) break;
        t += dist * 0.6;
    }
    
    // Post Processing
    finalCol = pow(finalCol, vec3(1.1)); // Contrast
    finalCol = mix(finalCol, vec3(0.0), smoothstep(4.2, 5.0, length(uv*4.0))); // Vignette

    fragColor = vec4(finalCol, 1.0);
}

Buffer C (iChannel2)

// "The Trinity Collider"
// Three Channels fighting for existence.
// Ch 1: Pink Organic Gyroid
// Ch 2: Blue Crystal Gyroid
// Ch 3: The "Digital Rot" (A hidden interference field)
// Interaction: Ch 3 forces the others into a glitchy wireframe mode upon contact.

// --- 🎛️ THE MIXER ---
#define CAMERA_DIST 8.5
#define CORE_SIZE 4.5
#define ROT_SPEED 0.3
#define INTERFERENCE_SCALE 5.0 // How detailed the "Rot" is

// --- 🎨 PALETTES ---

// Ch 1: Warm Organic
vec3 palOrganic(float t) {
    return vec3(0.5,0.5,0.5) + vec3(0.5,0.5,0.5)*cos(6.28*(vec3(1.0,1.0,1.0)*t+vec3(0.3,0.2,0.2)));
}
// Ch 2: Cool Crystal
vec3 palCrystal(float t) {
    return vec3(0.5,0.5,0.5) + vec3(0.5,0.5,0.5)*cos(6.28*(vec3(1.0,1.0,1.0)*t+vec3(0.0,0.1,0.2)));
}
// Ch 3: TOXIC GLITCH (High contrast Green/Magenta)
vec3 palGlitch(float t) {
    vec3 c = vec3(0.0, 1.0, 0.0); // Acid Green base
    if (sin(t*20.0) > 0.0) c = vec3(1.0, 0.0, 1.0); // Flicker Magenta
    return c;
}

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

// --- 🧬 SHAPE FUNCTIONS ---

// Smooth Gyroid
float sdGyroid(vec3 p, float s, float t, float b) {
    p *= s;
    return abs(dot(sin(p), cos(p.yzx)) - b)/s - t;
}

// "Digital" Gyroid (Manhattan/Blocky logic)
// This creates the Ch 3 interference pattern
float sdTechGyroid(vec3 p, float s) {
    p *= s;
    // Using sharp abs() and logic to make it look like circuitry
    float g = abs(dot(sin(p), cos(p.yzx)));
    return (g - 0.2)/s; // No thickness, just a field
}

// --- 🗺️ THE WORLD MAP ---
// Returns: vec3( distance, mix_ratio, interference_level )
vec3 map(vec3 p) {
    vec3 p0 = p;
    float sphere = length(p) - CORE_SIZE;
    
    // Animate space
    p.xy *= rot(iTime * 0.1);
    p.z += iTime * 0.2;
    
    // --- CH 1 & 2: THE PHYSICAL BODIES ---
    float g1 = sdGyroid(p, 2.8, 0.1, 0.0); // Pink
    
    vec3 p2 = p + vec3(2.0, 0.0, 0.0); // Offset Blue
    p2.yz *= rot(iTime * 0.4); 
    float g2 = sdGyroid(p2, 4.0, 0.03, 0.0); // Blue
    
    // Blend Ch 1 & 2
    float h = clamp(0.5 + 0.5 * (g2 - g1) / 0.5, 0.0, 1.0);
    float physicalDist = mix(g2, g1, h) - 0.5 * h * (1.0 - h);
    
    // --- CH 3: THE DIGITAL INTERFERENCE ---
    // This object is INVISIBLE, but we track where it IS.
    vec3 p3 = p0;
    p3.xz *= rot(-iTime * 0.5); // Spin opposite
    float g3 = sdTechGyroid(p3, INTERFERENCE_SCALE);
    
    // Calculate "Corruption"
    // If we are close to the physical surface AND inside the Glitch field
    float corruption = smoothstep(0.1, -0.1, g3); 
    
    // Crop to sphere
    float d = max(physicalDist, sphere);
    
    return vec3(d, h, corruption);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    vec2 uv = (fragCoord * 2.0 - iResolution.xy) / iResolution.y;
    
    // Camera
    vec3 ro = vec3(0.0, 0.0, -CAMERA_DIST);
    vec3 rd = normalize(vec3(uv, 1.0));
    ro.xz *= rot(iTime * 0.2);
    rd.xz *= rot(iTime * 0.2);
    
    float t = 0.0;
    vec3 dVec = vec3(0.0);
    vec3 glow = vec3(0.0);
    
    for(int i=0; i<80; i++) {
        vec3 p = ro + rd * t;
        dVec = map(p); // x=dist, y=mix, z=corruption
        
        float dist = dVec.x;
        float mixRatio = dVec.y;
        float isCorrupted = dVec.z; // 0.0 = clean, 1.0 = glitched
        
        // --- TRIPLE CHANNEL COLORING ---
        float proximity = 1.0 / (abs(dist) * 20.0 + 1.0);
        
        // 1. Base Colors (Pink vs Blue)
        vec3 c1 = palOrganic(length(p)*0.2 + iTime);
        vec3 c2 = palCrystal(length(p)*0.5 - iTime);
        vec3 baseCol = mix(c2, c1, mixRatio);
        
        // 2. Collision Spark (White Hot)
        float collision = 1.0 - abs(mixRatio * 2.0 - 1.0);
        collision = pow(collision, 8.0);
        baseCol += vec3(1.0) * collision;
        
        // 3. APPLY THE CORRUPTION (Channel 3)
        // If 'isCorrupted' is high, we switch to "Wireframe Mode"
        vec3 glitchCol = palGlitch(length(p) * 2.0 + iTime * 5.0);
        
        // Wireframe logic: Only glow at very specific intervals
        float wire = sin(p.x*30.0)*sin(p.y*30.0)*sin(p.z*30.0);
        if (wire < 0.95) glitchCol *= 0.1; // Darken inside logic
        else glitchCol *= 5.0; // Bright nodes
        
        // MIX: Standard Reality vs. Glitch Reality
        vec3 finalAtom = mix(baseCol, glitchCol, isCorrupted);
        
        glow += finalAtom * proximity * 0.05;
        
        if(abs(dist) < 0.001 || t > 20.0) break;
        t += dist * 0.6;
    }
    
    // Maximalist Contrast
    glow = pow(glow, vec3(1.2));
    // Add noise grain
    float noise = fract(sin(dot(uv, vec2(12.9, 78.2)))*43758.5);
    glow += noise * 0.05;

    fragColor = vec4(glow, 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