/ math, structure unit:{x%\:sqrt wsum[x]x}; cut:{(x*!-_-(#y)%x)_y}; vs1:{(&x#x;(x*x)#!x)} / ray_sphere factor A:{[p;q;c;r]t:e[i]+f:sqrt d i:&~0>d:(r*r)+(e*e:wsum[v]q)-wsum[v]v:c-p;(t;i;e;f)} / ray_sphere S:{[m;p;q;c;r]{[m;t;i;e;f]@[m#0w;i;:;@[@[t;&j;:;0w];l k;:;u k:&0t]]}[m]. A[p;q;c]r} / boolean ray_sphere R:{[b;p;q;c;r]{[b;t;i]@[b;i@&~0>t;:;1b]}[b]. 2#A[p;q;c]r} / intersect I:{[m;p;q;z;s;o].[z;(::;i);:;$[@s;(,t),unit p[;i]+(q[;i]*\:t@:i:&z[0]>t:S[m;p;q;s]o)-s z[;i:&z[0]>S[m;p;q]. s]K[I;p;q;i]/o]]} / boolean intersect J:{[m;p;q;b;s;o]$[@s;R[b;p;q;s]o;@[b;i;:;b[i:&R[m#0b;p;q]. s]K[J;p;q;i]/o]]} / intersect recursion K:{[f;p;q;i;x;y]f[#i;p[;i];q[;i];x]. y} / ray_trace T:{[m;p;q;s;o]n:#j:&0>g:wsum[h[1;;i:&~0w=l:**h:0 1_I[m;p;q;m#'0w 0 0 0;s;o]]]u:unit -1 -3 2. @[m#0.;i k;:;-g k:j@&~J[n;p[;k]+(l[k]*/:q[;k])+h[1;;k:i j]*sqrt xexp[2;-42];n#'-u;n#0b;s]o]} / accumulate N:{[m;n;i;o;x;y]x+T[m;m#'0 0 -4.;unit(i+(y%4)-.5*n),,m#n*1.]. o} / main M:{[k;n]F[n]@,/|+cut[n]0 N[n*n;n;vs1 n;C[k;0 -1 0.]1.]/+vs1 4} / PGM file F:{[n;v]"P5\n",(,/" ",'$n,n),"\n255\n","c"$_.5+15.9375*v} / create scene = sphere or (sphere;5-scenes) C:{[k;c;r]$[k=1;(c;r);((c;r*3);(,(c;r)),C[k-1;;r%2]'+c+(-3 -3 3 3;3 3 3 3;-3 3 -3 3)*r%sqrt 12)]} \t q:M[6]160 `:rt.pgm 1:q