func hitf(sph, x, y) { x -= sph[0] y -= sph[1] var z = (sph[3]**2 - (x**2 + y**2)) z < 0 && return nil z.sqrt! [sph[2] - z, sph[2] + z] } func normalize(v) { v / v.abs } func dot(x, y) { max(0, x*y) } var pos = [120, 120, 0, 120] var neg = [-77, -33, -100, 190] var light = normalize(Vector(-12, 13, -10)) func draw(k, amb) { STDOUT.binmode(':raw') print ("P5\n", pos[0]*2 + 3, " ", pos[1]*2 + 3, "\n255\n") for y in ((pos[1] - pos[3] - 1) .. (pos[1] + pos[3] + 1)) { var row = [] for x in ((pos[0] - pos[3] - 1) .. (pos[0] + pos[3] + 1)) { var hit = 0 var hs = [] var h = hitf(pos, x, y) if (!h) { hit = 0; h = [0, 0] } elsif (!(hs = hitf(neg, x, y))) { hit = 1; hs = [0, 0] } elsif (hs[0] > h[0]) { hit = 1 } elsif (hs[1] > h[0]) { hit = (hs[1] > h[1] ? 0 : 2) } else { hit = 1 } var (val, v) given(hit) { when (0) { val = 0} when (1) { v = Vector(x-pos[0], y-pos[1], h[0]-pos[2]) } default { v = Vector(neg[0]-x, neg[1]-y, neg[2]-hs[1]) } } if (defined(v)) { v = normalize(v) val = int((dot(v, light)**k + amb) * 255) val = (val > 255 ? 255 : (val < 0 ? 0 : val)) } row.append(val) } print 'C*'.pack(row...) } } draw(2, 0.2)