open .fs {
"DESCRIPTION" : "Borealis: curtains of aurora ripple and fold over a still night — green low, violet high — above a starfield and a dark mountain horizon with a faint mirror in the water below. Folds and shimmer run on a circular phase so it loops seamlessly over 16s." ,
"CREDIT" : "glslop agent (Claude)" ,
"CATEGORIES" : [ "aurora" , "sky" , "atmospheric" , "neon" , "landscape" ] ,
"INPUTS" : [
{ "NAME" : "speed" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 3.0 } ,
{ "NAME" : "glow" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.3 , "MAX" : 3.0 } ,
{ "NAME" : "hue" , "TYPE" : "float" , "DEFAULT" : 0.0 , "MIN" : 0.0 , "MAX" : 1.0 } ,
{ "NAME" : "curtains" , "TYPE" : "long" , "DEFAULT" : 3 , "MIN" : 1 , "MAX" : 6 } ,
{ "NAME" : "zoom" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.6 , "MAX" : 1.6 }
]
}
#define PI 3.14159265359
#define TAU 6.28318530718
#define MAXC 6
const float PERIOD = 16.0 ;
float hash (vec2 p){ return fract (sin (dot (p, vec2 (127.1 , 311.7 ))) * 43758.5453 ); }
float noise (vec2 p){
vec2 i = floor (p), f = fract (p); f = f * f * (3.0 - 2.0 * f);
float a = hash (i), b = hash (i + vec2 (1 , 0 )), c = hash (i + vec2 (0 , 1 )), d = hash (i + vec2 (1 , 1 ));
return mix (mix (a, b, f.x), mix (c, d, f.x), f.y);
}
float fbm (vec2 p){ float s = 0.0 , a = 0.5 ; for (int i = 0 ; i < 4 ; i++){ s += a * noise (p); p *= 2.0 ; a *= 0.5 ; } return s; }
void main (){
vec2 uv = (gl_FragCoord .xy - 0.5 * RENDERSIZE .xy) / RENDERSIZE .y;
uv /= zoom;
float ph = fract (TIME * speed / PERIOD);
float th = TAU * ph;
vec2 orb = 0.5 * vec2 (cos (th), sin (th));
vec3 col = mix (vec3 (0.02 , 0.03 , 0.07 ), vec3 (0.0 , 0.01 , 0.03 ), uv.y * 0.5 + 0.5 );
vec2 sp = uv * 12.0 ;
vec2 sg = floor (sp);
float sh = hash (sg);
float star = smoothstep (0.10 , 0.0 , length (fract (sp) - vec2 (hash (sg + 1.0 ), hash (sg + 2.0 ))));
col += vec3 (0.9 , 0.95 , 1.0 ) * star * step (0.88 , sh) * (0.6 + 0.4 * sin (th * 3.0 + sh * 30.0 ));
vec3 aur = vec3 (0.0 );
for (int i = 0 ; i < MAXC; i++){
if (i >= curtains) break ;
float fi = float (i);
float fold = 0.35 * sin (uv.y * 1.6 + th + fi * 2.1 )
+ 0.18 * sin (uv.y * 3.7 - th * 2.0 + fi);
float cx = -0.1 + 0.28 * (fi - float (curtains - 1 ) * 0.5 ) + fold;
float streak = fbm (vec2 ((uv.x - cx) * 7.0 + fi * 9.0 , uv.y * 1.4 ) + orb);
streak = pow (streak, 1.7 ) + 0.5 * pow (streak, 4.0 );
float env = exp (-pow ((uv.x - cx) / 0.24 , 2.0 ));
float vfade = smoothstep (1.0 , -0.45 , uv.y) * smoothstep (-0.55 , -0.15 , uv.y);
float a = streak * env * vfade;
float hgt = clamp (uv.y * 0.85 + 0.45 , 0.0 , 1.0 );
vec3 c = mix (vec3 (0.1 , 1.0 , 0.35 ), vec3 (0.55 , 0.1 , 1.0 ), hgt);
c = mix (c, vec3 (1.0 , 0.25 , 0.7 ), smoothstep (0.55 , 1.0 , hgt) * 0.7 );
aur += c * a;
}
col += aur * 2.6 * glow;
float horizon = -0.28 + 0.04 * fbm (vec2 (uv.x * 2.0 + 3.0 , 0.0 )) - 0.02 ;
float land = smoothstep (0.01 , -0.01 , uv.y - horizon);
if (uv.y < horizon){
vec2 ruv = vec2 (uv.x, 2.0 * horizon - uv.y);
ruv.x += 0.02 * sin (uv.y * 30.0 + th);
float rh = clamp (ruv.y * 0.9 + 0.4 , 0.0 , 1.0 );
vec3 rc = mix (vec3 (0.15 , 1.0 , 0.45 ), vec3 (0.5 , 0.15 , 0.95 ), rh);
float renv = 0.0 ;
for (int i = 0 ; i < MAXC; i++){ if (i >= curtains) break ; float fi = float (i);
float fold = 0.35 * sin (ruv.y * 1.6 + th + fi * 2.1 ) + 0.18 * sin (ruv.y * 3.7 - th * 2.0 + fi);
float cx = -0.1 + 0.28 * (fi - float (curtains - 1 ) * 0.5 ) + fold;
renv += exp (-pow ((ruv.x - cx) / 0.22 , 2.0 )) * pow (fbm (vec2 ((ruv.x - cx) * 6.0 + fi * 9.0 , ruv.y * 1.6 ) + orb), 2.2 );
}
col += rc * renv * 0.18 * glow * smoothstep (horizon - 0.5 , horizon, uv.y);
}
col = mix (col, vec3 (0.005 , 0.01 , 0.02 ), land);
col = col / (1.0 + col);
col = pow (col, vec3 (0.85 ));
col *= 1.0 - 0.18 * dot (uv * zoom, uv * zoom);
gl_FragColor = vec4 (col, 1.0 );
}