open .fs {
"DESCRIPTION" : "Persistent liquid-chrome ribbons stirred by orbiting vortices." ,
"INPUTS" : [
{ "NAME" : "motion" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 2.5 } ,
{ "NAME" : "swirl" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 2.0 } ,
{ "NAME" : "trail" , "TYPE" : "float" , "DEFAULT" : 0.986 , "MIN" : 0.94 , "MAX" : 0.999 } ,
{ "NAME" : "hueShift" , "TYPE" : "float" , "DEFAULT" : 0.08 , "MIN" : 0.0 , "MAX" : 1.0 }
] ,
"PASSES" : [
{ "TARGET" : "paint" , "PERSISTENT" : true , "FLOAT" : true } ,
{ }
]
}
#define TAU 6.28318530718
vec3 palette (float t) {
return 0.5 + 0.5 * cos (TAU * (t + hueShift + vec3 (0.00 , 0.29 , 0.57 )));
}
vec2 vortex (vec2 p, vec2 center, float spin) {
vec2 d = p - center;
float influence = exp (-dot (d, d) * 13.0 );
return vec2 (-d.y, d.x) * influence * spin;
}
void main () {
vec2 uv = isf_FragNormCoord ;
if (PASSINDEX == 0 ) {
float t = TIME * motion;
float frameStep = min (TIMEDELTA * 60.0 , 2.0 );
vec2 p = uv - 0.5 ;
p.x *= RENDERSIZE .x / RENDERSIZE .y;
vec2 a = vec2 (0.27 * cos (t * 0.41 ), 0.24 * sin (t * 0.53 ));
vec2 b = vec2 (0.25 * cos (t * 0.37 + 3.1 ), 0.28 * sin (t * 0.46 + 2.2 ));
vec2 vel = vortex (p, a, 2.1 ) + vortex (p, b, -1.8 );
vel += vec2 (
sin (TAU * uv.y * 2.0 + t * 0.4 ),
cos (TAU * uv.x * 2.0 - t * 0.3 )
) * 0.055 ;
vel *= swirl;
vel.x /= RENDERSIZE .x / RENDERSIZE .y;
vec2 back = uv - vel * (0.014 * frameStep * motion);
vec2 px = 1.0 / RENDERSIZE ;
vec3 old = IMG_NORM_PIXEL (paint, back).rgb * 0.70 ;
old += IMG_NORM_PIXEL (paint, back + vec2 (px.x, 0.0 )).rgb * 0.075 ;
old += IMG_NORM_PIXEL (paint, back - vec2 (px.x, 0.0 )).rgb * 0.075 ;
old += IMG_NORM_PIXEL (paint, back + vec2 (0.0 , px.y)).rgb * 0.075 ;
old += IMG_NORM_PIXEL (paint, back - vec2 (0.0 , px.y)).rgb * 0.075 ;
old *= pow (trail, frameStep);
vec2 dropA = p - a;
vec2 dropB = p - b;
float injectA = smoothstep (0.046 , 0.0 , length (dropA));
float injectB = smoothstep (0.040 , 0.0 , length (dropB));
vec2 cpos = vec2 (0.18 * sin (t * 0.68 ), 0.30 * cos (t * 0.29 ));
float injectC = smoothstep (0.034 , 0.0 , length (p - cpos));
vec3 fresh = palette (t * 0.035 + length (a) + 0.12 ) * injectA;
fresh += palette (t * 0.035 + length (b) + 0.62 ) * injectB;
fresh += palette (t * 0.035 + length (cpos) + 0.36 ) * injectC;
float boundary = smoothstep (0.0 , 0.03 , uv.x)
* smoothstep (0.0 , 0.03 , 1.0 - uv.x)
* smoothstep (0.0 , 0.03 , uv.y)
* smoothstep (0.0 , 0.03 , 1.0 - uv.y);
vec3 next = max (old, fresh * 0.72 ) * boundary;
gl_FragColor = vec4 (clamp (next, 0.0 , 2.0 ), 1.0 );
} else {
vec2 uv2 = isf_FragNormCoord ;
vec2 px = 1.0 / RENDERSIZE ;
vec3 c = IMG_THIS_PIXEL (paint).rgb;
float l = dot (c, vec3 (0.3333 ));
float lx = dot (IMG_NORM_PIXEL (paint, uv2 + vec2 (px.x, 0.0 )).rgb, vec3 (0.3333 ));
float ly = dot (IMG_NORM_PIXEL (paint, uv2 + vec2 (0.0 , px.y)).rgb, vec3 (0.3333 ));
vec2 grad = vec2 (lx - l, ly - l);
float rim = clamp (length (grad) * 28.0 , 0.0 , 1.0 );
vec3 chrome = c * (0.34 + 1.35 * l);
chrome += rim * palette (0.16 + l * 0.22 ) * 0.72 ;
chrome += pow (max (l, 0.0 ), 3.0 ) * vec3 (0.8 , 0.9 , 1.0 );
chrome = chrome / (1.0 + 0.65 * chrome);
gl_FragColor = vec4 (chrome, 1.0 );
}
}