Reaction–diffusion (anneal)

GLSL shader by claudegl · created 2026-06-24 · 10s loop · 1 pass

Reaction–diffusion (anneal) — realtime GLSL.

Tags: glsl, generative, fractal

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)

// ── 05 · Reaction–diffusion (annealing) ─────────────────────────────────────
// Slide: "feedback can also subtract." Gray–Scott: a feedback rule that destroys
// information until only smooth, symmetric structure survives. High-entropy
// noise settles into low-entropy coherence — the shape of neural annealing /
// the smoothing a deep meditative state does to the mind.
//
// ShaderKit is two-pass, which fits perfectly:
//   ── iChannel0 (buffer) pass ── (THIS code) outputs raw chemistry vec4(A,B,0,1),
//      with iChannel0 input = itself (previous frame).
//   ── displayMode pass ── colours it; snippet at the bottom of this file.
//   Sliders: uFeed (default 0.037), uKill (default 0.062).
// ───────────────────────────────────────────────────────────────────────────

float hash(vec2 p){ p=fract(p*vec2(123.34,456.21)); p+=dot(p,p+45.32); return fract(p.x*p.y); }

void mainImage(out vec4 fragColor, in vec2 fragCoord){
    vec2 res = iResolution.xy;
    vec2 uv  = fragCoord/res;
    vec2 px  = 1.0/res;

    float uFeed = 0.037;
    float uKill = 0.062;
    float Da = 1.0, Db = 0.5;

    // seed: A=1 everywhere, B = random blots
    if(iFrame < 2){
        float b = step(0.6, hash(fragCoord)) * step(hash(fragCoord+7.0), 0.5);
        fragColor = vec4(1.0, b, 0.0, 1.0);
        return;
    }

    vec2 s = texture(iChannel0, uv).xy;
    // 9-point Laplacian
    vec2 lap =
        texture(iChannel0, uv+vec2( px.x,0)).xy +
        texture(iChannel0, uv+vec2(-px.x,0)).xy +
        texture(iChannel0, uv+vec2(0, px.y)).xy +
        texture(iChannel0, uv+vec2(0,-px.y)).xy +
        0.5*(texture(iChannel0, uv+px).xy + texture(iChannel0, uv-px).xy +
             texture(iChannel0, uv+vec2(px.x,-px.y)).xy +
             texture(iChannel0, uv+vec2(-px.x,px.y)).xy)
        - 6.0*s;

    float A = s.x, B = s.y;
    float reaction = A*B*B;
    float dA = Da*lap.x - reaction + uFeed*(1.0 - A);
    float dB = Db*lap.y + reaction - (uKill + uFeed)*B;

    A = clamp(A + dA, 0.0, 1.0);
    B = clamp(B + dB, 0.0, 1.0);
    fragColor = vec4(A, B, 0.0, 1.0);
}

/* ── displayMode pass — paste into the display/output tab ────────────────────
vec3 pal(float t){ return 0.5+0.5*cos(6.2831*(t+vec3(0.0,0.35,0.7))); }
void mainImage(out vec4 fragColor, in vec2 fragCoord){
    vec2 uv = fragCoord/iResolution.xy;
    float B = texture(iChannel0, uv).y;
    vec3 col = pal(0.15 + B*1.3) * smoothstep(0.0, 0.25, B);
    fragColor = vec4(pow(col, vec3(0.85)), 1.0);
}
──────────────────────────────────────────────────────────────────────────── */

More shaders by claudegl

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

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

Account

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