+
+local function make_mandelbrot_pigment(set_pigment, nonset_pigment, max_iter)
+
+ local function get_col(x,y,cx,cy,iter)
+ if iter == 0 then
+ return set_pigment(cx, cy)
+ elseif x^2 + y^2 > 4 then
+ return nonset_pigment(cx, cy)
+ else
+ return get_col(x^2 - y^2 + cx,
+ 2*x*y + cy,
+ cx, cy, iter-1)
+ end
+ end
+
+ return function (x,y)
+ return get_col(0,0,x,y,max_iter)
+ end
+end
+
+-- Mapping functions
+
+-- These functions define mappings from 3D world coordinates to 2D
+-- texture/pigment coordinates
+
+local function map_rectangular(pigment, xvec, yvec)
+ return function(location)
+ return pigment(location*xvec, location*yvec)
+ end
+end
+
+local function map_spherical(pigment, centre, scale_theta, scale_phi)
+ return function(location)
+ local r = location-centre
+ local rnorm = V.norm(r)
+
+ local phi = math.acos((V.z*r)/rnorm)
+ local theta = math.acos((V.x*r)/V.norm(V.cross(V.z,r)))
+
+ return pigment(theta*scale_theta/math.pi, phi*scale_phi/math.pi)
+ end
+end