open .fs {
"DESCRIPTION" : "A druse of quartz: a cluster of hexagonal crystal points fanning out from a common base, raymarched from exact hex-prism distance fields. Translucent amethyst bodies with bright Fresnel edges, thin-film iridescence sliding across the facets, and a violet inner glow. The cluster turns once for a seamless loop." ,
"CREDIT" : "glslop agent (Claude)" ,
"CATEGORIES" : [ "crystal" , "raymarch" , "mineral" , "iridescence" , "3d" ] ,
"INPUTS" : [
{ "NAME" : "speed" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 3.0 } ,
{ "NAME" : "hue" , "TYPE" : "float" , "DEFAULT" : 0.74 , "MIN" : 0.0 , "MAX" : 1.0 } ,
{ "NAME" : "irid" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 2.0 } ,
{ "NAME" : "glowAmt" , "TYPE" : "float" , "DEFAULT" : 1.0 , "MIN" : 0.0 , "MAX" : 2.0 } ,
{ "NAME" : "count" , "TYPE" : "long" , "DEFAULT" : 7 , "MIN" : 3 , "MAX" : 9 }
]
}
#define PI 3.14159265359
#define TAU 6.28318530718
#define GA 2.39996323
const float PERIOD = 16.0 ;
vec3 pal (float t){ return 0.5 + 0.5 *cos (TAU*(t + vec3 (0.0 , 0.33 , 0.66 ))); }
mat3 rotY (float a){ float c=cos (a), s=sin (a); return mat3 (c,0 ,-s, 0 ,1 ,0 , s,0 ,c); }
mat3 align (vec3 d){
vec3 z = normalize (d);
vec3 up = abs (z.y) < 0.98 ? vec3 (0.0 ,1.0 ,0.0 ) : vec3 (1.0 ,0.0 ,0.0 );
vec3 x = normalize (cross (up, z));
vec3 y = cross (z, x);
return mat3 (x, y, z);
}
float sdHexPrism (vec3 p, vec2 h){
const vec3 k = vec3 (-0.8660254 , 0.5 , 0.57735 );
p = abs (p);
p.xy -= 2.0 *min (dot (k.xy, p.xy), 0.0 )*k.xy;
vec2 d = vec2 (length (p.xy - vec2 (clamp (p.x, -k.z*h.x, k.z*h.x), h.x))*sign (p.y - h.x),
p.z - h.y);
return min (max (d.x, d.y), 0.0 ) + length (max (d, 0.0 ));
}
float crystal (vec3 q, float len, float rad){
float apex = len + rad*1.9 ;
float body = sdHexPrism (q - vec3 (0.0 , 0.0 , apex*0.5 ), vec2 (rad, apex*0.5 ));
float ax = apex - q.z;
float cone = length (q.xy) - max (0.0 , ax)*0.60 ;
return max (body, cone);
}
float map (vec3 p){
float d = 1e9 ;
for (int i = 0 ; i < 9 ; i++){
if (i >= int (count)) break ;
float fi = float (i);
float tilt = 0.10 + 0.62 *fract (fi*0.37 + 0.13 );
float az = fi*GA;
vec3 dir = vec3 (sin (tilt)*cos (az), cos (tilt), sin (tilt)*sin (az));
float len = 0.85 + 0.55 *fract (fi*0.61 );
float rad = 0.085 + 0.04 *fract (fi*0.53 );
vec3 base = dir*0.12 ;
vec3 q = (p - base) * align (dir);
d = min (d, crystal (q, len, rad));
}
return d;
}
vec3 normal (vec3 p){
vec2 e = vec2 (0.0012 , 0.0 );
return normalize (vec3 (
map (p+e.xyy) - map (p-e.xyy),
map (p+e.yxy) - map (p-e.yxy),
map (p+e.yyx) - map (p-e.yyx)));
}
void main (){
vec2 uv = (2.0 *gl_FragCoord .xy - RENDERSIZE .xy) / RENDERSIZE .y;
float ph = fract (TIME * speed / PERIOD);
float th = TAU * ph;
mat3 spin = rotY (th);
vec3 ro = spin * vec3 (0.0 , 0.45 , 2.35 );
vec3 ta = vec3 (0.0 , 0.62 , 0.0 );
vec3 fw = normalize (ta - ro);
vec3 rt = normalize (cross (vec3 (0 ,1 ,0 ), fw));
vec3 up = cross (fw, rt);
vec3 rd = normalize (uv.x*rt + uv.y*up + 2.0 *fw);
float t = 0.0 ;
float glow = 0.0 ;
bool hit = false ;
for (int i = 0 ; i < 90 ; i++){
vec3 p = ro + rd*t;
float d = map (p);
glow += glowAmt * 0.012 / (1.0 + 28.0 *d*d);
if (d < 0.0006 *t){ hit = true ; break ; }
t += d*0.8 ;
if (t > 8.0 ) break ;
}
vec3 col = vec3 (0.0 );
vec3 bg = mix (vec3 (0.02 ,0.015 ,0.045 ), vec3 (0.005 ,0.005 ,0.02 ), uv.y*0.5 +0.5 );
col = bg;
if (hit){
vec3 p = ro + rd*t;
vec3 n = normal (p);
float fres = pow (1.0 - max (dot (n, -rd), 0.0 ), 2.5 );
vec3 body = vec3 (0.42 , 0.20 , 0.72 );
vec3 irc = 0.5 + 0.5 *cos (TAU*(0.6 + 0.6 *fres + 0.4 *n.y) + vec3 (0.0 , 1.8 , 3.4 ));
col = body * (0.5 + 0.7 *(0.5 +0.5 *n.y));
col += vec3 (0.45 , 0.22 , 0.85 ) * (1.0 - fres) * 0.55 ;
col += irc * (0.20 + 0.7 *fres) * irid;
col += vec3 (1.0 , 0.96 , 1.0 ) * pow (fres, 2.0 ) * 0.8 ;
float sheen = max (dot (n, normalize (vec3 (0.5 , 0.85 , 0.35 ))), 0.0 );
col += vec3 (0.95 , 0.85 , 1.0 ) * pow (sheen, 16.0 ) * 0.9 ;
}
col += vec3 (0.5 , 0.26 , 0.95 ) * glow * 1.1 ;
col = col / (1.0 + col);
col = pow (col, vec3 (0.85 ));
gl_FragColor = vec4 (col, 1.0 );
}