open .fs {
"DESCRIPTION" : "Aurora over a mountain range, mirrored in a still rippling lake under a field of stars." ,
"CREDIT" : "claude-opus-4-8" ,
"INPUTS" : [
{ "NAME" : "speed" , "TYPE" : "float" , "DEFAULT" : 0.5 , "MIN" : 0.0 , "MAX" : 2.0 } ,
{ "NAME" : "bands" , "TYPE" : "float" , "DEFAULT" : 5.0 , "MIN" : 2.0 , "MAX" : 9.0 } ,
{ "NAME" : "intensity" , "TYPE" : "float" , "DEFAULT" : 0.8 , "MIN" : 0.2 , "MAX" : 1.6 } ,
{ "NAME" : "hue" , "TYPE" : "float" , "DEFAULT" : 0.4 , "MIN" : 0.0 , "MAX" : 1.0 }
]
}
const float HY = 0.46 ;
float hash (vec2 p){ p = fract (p * vec2 (123.34 , 456.21 )); p += dot (p, p + 45.32 ); return fract (p.x * p.y); }
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 , 0.0 )), c = hash (i + vec2 (0.0 , 1.0 )), d = hash (i + vec2 (1.0 , 1.0 ));
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 = p * 2.0 + 3.0 ; a *= 0.5 ; } return s; }
vec3 palette (float t){ return 0.5 + 0.5 * cos (6.28318 * (t + vec3 (0.0 , 0.33 , 0.67 ) + hue)); }
float ridge (float x){
float far = 0.06 + 0.05 * fbm (vec2 (x * 2.2 + 11.0 , 0.0 ));
float near = 0.02 + 0.11 * fbm (vec2 (x * 1.4 - 5.0 , 7.0 ));
return max (far, near);
}
vec3 auroraCol (float x, float y, float t){
vec3 c = vec3 (0.0 );
for (int i = 0 ; i < 9 ; i++){
if (float (i) >= bands) break ;
float fi = float (i);
float yC = 0.64 + 0.07 * fi;
float wob = 0.10 * noise (vec2 (x * 1.5 + fi, t * 0.5 + fi * 3.0 )) + 0.04 * sin (x * 3.0 + t + fi);
float d = abs (y - (yC + wob));
float curt = exp (-d * 15.0 );
curt *= 0.55 + 0.45 * noise (vec2 (x * 22.0 , t + fi * 5.0 ));
c += curt * palette (0.12 * fi + 0.3 + 0.1 * x) * intensity;
}
return c * smoothstep (HY - 0.02 , HY + 0.12 , y);
}
vec3 sceneAbove (vec2 q, float t){
float x = q.x, y = q.y;
vec3 col = mix (vec3 (0.03 , 0.04 , 0.10 ), vec3 (0.0 , 0.0 , 0.015 ), clamp ((y - 0.4 ) / 0.6 , 0.0 , 1.0 ));
vec2 g = floor (vec2 (x, y) * 130.0 );
float h = hash (g);
col += smoothstep (0.986 , 1.0 , h) * (0.6 + 0.4 * sin (t * 3.0 + h * 40.0 )) * smoothstep (0.5 , 0.75 , y);
col += auroraCol (x, y, t);
float top = HY + ridge (x);
if (y < top){
float k = top - y;
vec3 mnt = mix (vec3 (0.05 , 0.06 , 0.11 ), vec3 (0.01 , 0.01 , 0.03 ), smoothstep (0.0 , 0.16 , k));
mnt += auroraCol (x, top, t) * 0.35 * exp (-k * 26.0 );
col = mnt;
}
return col;
}
void main (){
vec2 uv = gl_FragCoord .xy / RENDERSIZE ;
float asp = RENDERSIZE .x / RENDERSIZE .y;
float x = (uv.x - 0.5 ) * asp;
float t = TIME * speed;
vec3 col;
if (uv.y >= HY){
col = sceneAbove (vec2 (x, uv.y), t);
} else {
float depth = HY - uv.y;
float ripple = 0.010 * sin (uv.y * 55.0 - t * 2.0 ) * (0.3 + depth * 1.5 );
ripple += 0.006 * (fbm (vec2 (x * 7.0 , uv.y * 18.0 - t)) - 0.5 );
vec2 rc = vec2 (x + ripple, 2.0 * HY - uv.y + ripple * 0.4 );
vec3 refl = sceneAbove (rc, t);
refl *= vec3 (0.62 , 0.72 , 0.92 );
refl = mix (refl, vec3 (0.0 , 0.02 , 0.05 ), smoothstep (0.0 , HY, depth) * 0.55 );
float spark = pow (max (0.0 , fbm (vec2 (x * 26.0 , uv.y * 26.0 - t * 3.0 )) - 0.55 ), 2.0 );
refl += spark * 0.5 * vec3 (0.7 , 0.9 , 1.0 );
col = refl;
}
col *= 1.0 - 0.25 * dot (uv - 0.5 , uv - 0.5 );
col = pow (max (col, 0.0 ), vec3 (0.9 ));
gl_FragColor = vec4 (col, 1.0 );
}