PRISMACORE_001 — Liquid Crystal Fever Dream

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

Domain-warped fbm field folded twice through itself, skinned in three-wavelength thin-film iridescence and mapped to a hot pink / electric cyan / acid lime / deep violet palette. Worley crystal facets bleed through the liquid substrate. Chromatic aberration splits the R and B channels across offset warp paths. CRT scanlines, grain, and vignette age the whole mess. ACES tonemapped so it doesn't eat your retinas. Math pretending to be alive for 0.2 seconds, then melting back into math.

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)

// PRISMACORE — shader_001
// Domain warp + thin-film iridescence + crystal facets + CRT damage
// Shadertoy: uses iTime, iResolution

#define PI  3.14159265
#define TAU 6.28318530

// ════════════════════════════════
// KNOBS — tweak these
// ════════════════════════════════
#define WARP_SCALE   2.5   // domain warp intensity
#define IRIDESCENCE  1.8   // thin-film color spread
#define GLITCH_AMT   0.3   // horizontal glitch band freq
#define DAMAGE       0.4   // CRT dirt/scanline/grain amount
#define CRYSTAL      0.6   // 0=smooth field, 1=hard facets
#define FLOW_SPEED   0.4   // animation rate multiplier
// ════════════════════════════════

// ---- HASH / NOISE ----
float hash(vec2 p) {
    p = fract(p * vec2(127.1, 311.7));
    p += dot(p, p + 19.19);
    return fract(p.x * p.y);
}
float hash1(float x) { return fract(sin(x * 127.1) * 43758.5); }
vec2  hash2(vec2 p)  { return vec2(hash(p), hash(p + 17.3)); }

float vnoise(vec2 p) {
    vec2 i = floor(p), f = fract(p);
    vec2 u = f * f * (3.0 - 2.0 * f);
    return mix(mix(hash(i), hash(i+vec2(1,0)), u.x),
               mix(hash(i+vec2(0,1)), hash(i+vec2(1,1)), u.x), u.y);
}

float fbm(vec2 p, int oct) {
    float v = 0.0, a = 0.5;
    for (int i = 0; i < 6; i++) {
        if (i >= oct) break;
        v += a * vnoise(p);
        p  = p * 2.1 + vec2(1.7, 9.2);
        a *= 0.5;
    }
    return v;
}

// ---- DOMAIN WARP (two-pass) ----
vec2 warp(vec2 p, float t) {
    float t1 = t * FLOW_SPEED;
    vec2 q = vec2(fbm(p + vec2(t1*0.7, 1.3), 4),
                  fbm(p + vec2(2.8, t1*0.5), 4));
    return p + q * (WARP_SCALE * 0.45);
}

// ---- CRYSTAL (Worley-ish) ----
float crystal(vec2 p) {
    vec2 i = floor(p), f = fract(p);
    float d = 1e9;
    for (int x=-1; x<=1; x++)
    for (int y=-1; y<=1; y++) {
        vec2 jit = hash2(i + vec2(x,y)) * 0.7 + 0.15;
        d = min(d, length(f - vec2(x,y) - jit));
    }
    return d;
}

// ---- THIN-FILM IRIDESCENCE ----
// Three-wavelength interference across a phase scalar
vec3 thinFilm(float phase, float strength) {
    return vec3(
        sin(phase * TAU * strength)              * 0.5 + 0.5,
        sin(phase * TAU * strength + TAU/3.0)   * 0.5 + 0.5,
        sin(phase * TAU * strength + 2.0*TAU/3.0) * 0.5 + 0.5
    );
}

// ---- GLITCH ----
vec2 glitch(vec2 uv, float t) {
    float band    = floor(uv.y * 20.0 + t * 7.3);
    float trigger = hash1(band + floor(t * 3.0));
    float shift   = (trigger > 1.0 - GLITCH_AMT)
                    ? (hash1(band) - 0.5) * 0.10 : 0.0;
    if (hash1(floor(t*13.0) + band*0.1) > 0.97)
        shift += (hash1(band*3.7) - 0.5) * 0.04;
    uv.x += shift;
    return uv;
}

// ---- CRT DAMAGE ----
float crt(vec2 uv, float t) {
    float scan = sin(uv.y * iResolution.y * 1.5) * 0.04 * DAMAGE;
    vec2  vig  = uv * 2.0 - 1.0;
    float v    = 1.0 - dot(vig, vig) * 0.4 * DAMAGE;
    float grain = (hash(uv * iResolution.xy + t * 1000.0) - 0.5) * 0.06 * DAMAGE;
    return v + scan + grain;
}

// ════════════════════════════════
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv  = fragCoord / iResolution.xy;
    float t  = iTime;
    float asp = iResolution.x / iResolution.y;

    // glitch UV first
    vec2 guv = glitch(uv, t);
    vec2 gp  = (guv * 2.0 - 1.0) * vec2(asp, 1.0);

    // double-pass warp
    vec2 wp  = warp(gp * 0.8 + 1.5, t);
    wp       = warp(wp + 2.3, t * 1.1);

    // base field
    float field = fbm(wp * 1.5, 5);
    float cry   = crystal(wp * 3.0 + t * 0.1);
    field = mix(field, cry, CRYSTAL * 0.5);

    // chromatic aberration offsets (separate R / B samples)
    float spl = 0.015 + sin(t * 0.7) * 0.008;
    vec2 rpOff = vec2(spl, 0.0);
    vec2 bpOff = vec2(-spl, spl * 0.5);
    float fR = fbm(warp((gp+rpOff)*0.8+1.5, t)*1.5, 5);
    float fB = fbm(warp((gp+bpOff)*0.8+1.5, t)*1.5, 5);

    // phase for iridescence
    float phase  = field + fbm(wp*2.0 + t*0.3, 3)*0.5;

    // thin-film → Lisa Frank palette
    vec3 film = thinFilm(phase, IRIDESCENCE);

    const vec3 PINK   = vec3(1.00, 0.07, 0.57);
    const vec3 CYAN   = vec3(0.00, 0.95, 1.00);
    const vec3 LIME   = vec3(0.60, 1.00, 0.00);
    const vec3 VIOLET = vec3(0.50, 0.00, 1.00);

    vec3 col = film.r * PINK + film.g * LIME + film.b * CYAN;

    // violet bleeds into dark crevices
    float dark = 1.0 - smoothstep(0.2, 0.6, field);
    col = mix(col, VIOLET * 0.8, dark * 0.6);

    // chromatic push on R and B channels
    vec3 filmR = thinFilm(fR + 0.1, IRIDESCENCE);
    vec3 filmB = thinFilm(fB - 0.1, IRIDESCENCE);
    col.r = mix(col.r, filmR.r * PINK.r + filmR.g * LIME.r, 0.4);
    col.b = mix(col.b, filmB.b * CYAN.b, 0.4);

    // exposure + gamma lift
    col  = pow(max(col, 0.0), vec3(0.8)) * 1.25;

    // CRT layer
    col *= crt(uv, t);

    // ACES tonemap
    col = col*(2.51*col+0.03) / (col*(2.43*col+0.59)+0.14);

    fragColor = vec4(clamp(col, 0.0, 1.0), 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