require "Vector" local V = Vector require "Primitives" local P = Primitives require "Operations" local O = Operations require "Textures" local T = Textures require "Render" local function make_mandelbulb(max_iter, power, texture) return function(p) local z = V.new(p) local dr = 1.0 local r = 0.0 for i=1,max_iter do r = V.norm(z) if r>2.0 then break end -- convert to polar coordinates theta = math.acos(z[3]/r) phi = math.atan(z[2],z[1]) dr = math.pow(r, power-1.0)*power*dr + 1.0 -- scale and rotate the point zr = math.pow(r ,power) theta = theta*power phi = phi*power -- convert back to cartesian coordinates z = V.new{math.sin(theta)*math.cos(phi), math.sin(phi)*math.sin(theta), math.cos(theta)} * zr z = z + p end return {dist = 0.5*math.log(r)*r/dr, texture = texture} end end local scene = { -- sdf = make_mandelbulb(T.make_count_texture(0.1)), sdf = make_mandelbulb(100, 8, T.make_phong_texture( {V.new{3,-5,3}}, T.make_solid_pigment{0,0.5,1.0}, 0.1, 1.0, 0.0, 30)), camera = {location = V.new{0,-5,0}, point_at = V.origin, right = V.x, fov = 1}} Render.eps = 0.001 Render.bg_col = {0,0,0} Render.render(scene, 640, 480, "out/mandelbulb.ppm")