SHARE
TWEET

Mandelbulb Codea

ezak Jan 25th, 2013 231 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. --# Main
  3. -- Mandlebulb
  4. displayMode(FULLSCREEN)
  5. function setup()
  6.     --noSmooth()
  7.  
  8.     t = vec3(0.591177,-0.381549,1)
  9.  
  10.     nbTouches = 0
  11.     touches = {}
  12.    
  13.     step = 0.0001
  14.     NB_PASS = 20
  15.     PASS = 0
  16.     PASS_DIR = 0
  17.    
  18.     scene = Scene(WIDTH,HEIGHT)
  19.  
  20.     T_BEGAN = false
  21.     T_ENDED = false
  22.  
  23.     zoomDir = -1
  24.  
  25. end
  26.  
  27. function draw()
  28.     local sh = scene.surface.shader
  29.     if PASS_DIR == 0 then PASS_DIR = 1 else PASS_DIR = 0 end
  30.     sh.PASS_DIR = PASS_DIR
  31.    
  32.     if zooming then
  33.         t.z = t.z + (1000/(100/t.z)/60*DeltaTime)*zoomDir
  34.         sh.ZOOM = t.z
  35.     end
  36.  
  37.     if T_BEGAN then
  38.         NB_PASS = 1
  39.         PASS = 0
  40.         sh.resolution = vec2(128, 96)
  41.         scene.buffer = image(128, 96)
  42.         T_BEGAN = false
  43.     end
  44.  
  45.     if T_ENDED then
  46.         if nbTouches == 0 then
  47.             scene:draw()
  48.             NB_PASS = 20
  49.             local w, h = spriteSize(scene.BG)
  50.             setContext(scene.BG)
  51.             sprite(scene.buffer, w/2, h/2, w)
  52.             sh.resolution = vec2(scene.w, scene.h)
  53.             scene.buffer = image(scene.w, scene.h)
  54.            
  55.             w, h = spriteSize(scene.buffer)
  56.             setContext(scene.buffer)
  57.             sprite(scene.BG, w/2, h/2, w)
  58.             setContext()
  59.         end
  60.         T_ENDED = false
  61.     else
  62.    
  63.         PASS = PASS + 1
  64.         if PASS > NB_PASS then
  65.             PASS = 1
  66.         end
  67.    
  68.         sh.PASS = PASS
  69.         sh.NB_PASS = NB_PASS
  70.        
  71.         scene:draw()
  72.     end
  73.  
  74. end
  75.  
  76.  
  77. --# Scene
  78. Scene = class()
  79.  
  80. function Scene:init(w, h)
  81.    
  82.     --set to non retina
  83.     self.w = w/2
  84.     self.h = h/2
  85.    
  86.     self.buffer = image(self.w, self.h)
  87.     self.BG = image(WIDTH, HEIGHT)
  88.    
  89.     local myShader = shader()
  90.     myShader.vertexProgram = self:vertexShader()
  91.     myShader.fragmentProgram = self:fragmentShader()
  92.    
  93.     self.surface = mesh()
  94.     self.surface.shader = myShader
  95.    
  96.     local cos = math.cos
  97.     local sin = math.sin
  98.    
  99.     local camPos = vec3(cos(t.y)*cos(t.x), sin(t.y), cos(t.y)*sin(t.x))*2
  100.     local camUp = vec3(0., 1., 0.)
  101.     local camTarget = vec3(0., 0., 0.)
  102.     local camDir = (camTarget-camPos):normalize()
  103.     local camSide = camDir:cross(camUp):normalize()
  104.     local camCDS = camDir:cross(camSide)
  105.    
  106.     local sh = self.surface.shader
  107.     sh.resolution = vec2(self.w, self.h)
  108.     sh.NB_PASS = NB_PASS
  109.     sh.PASS_DIR = PASS_DIR
  110.     sh.PASS = PASS
  111.     sh.sinTime = 1
  112.  
  113.     sh.camPos = camPos
  114.     sh.camDir = camDir
  115.     sh.camSide = camSide
  116.     sh.camCDS = camCDS
  117.     sh.ZOOM = t.z
  118.    
  119.     self.surface:addRect(0,0, WIDTH, HEIGHT)
  120. end
  121.  
  122. function Scene:draw()
  123.     --self.surface.shader.sinTime = .5+math.abs(math.sin(ElapsedTime))*2
  124.     setContext(self.buffer)
  125.     self.surface:draw()
  126.     setContext()
  127.     sprite(self.buffer, WIDTH/2, HEIGHT/2, WIDTH)
  128. end
  129.  
  130. --# BuildShaders
  131. function Scene:fragmentShader()
  132.     local source =
  133. [[
  134. #define PI 3.141592653589793
  135. #define BAILOUT sqrt(PI*.5)
  136. #define MAX_ITER 10
  137. #define MAX_DIST 2.2
  138. #define MAX_MARCH 30
  139.  
  140. #define DETAIL 0.0025
  141.  
  142. precision highp float;
  143.  
  144. uniform float sinTime;
  145. uniform float ZOOM;
  146.  
  147. uniform float NB_PASS;
  148. uniform float PASS;
  149. uniform int PASS_DIR;
  150.  
  151. uniform vec2 resolution;
  152. uniform vec3 camPos;
  153. uniform vec3 camDir;
  154. uniform vec3 camSide;
  155. uniform vec3 camCDS;
  156.  
  157.  
  158.  
  159. float mandelbulb(vec3 p, inout float color)
  160. {
  161.     vec3 v = p;
  162.     vec3 c = v;
  163.  
  164.     float r=0.0;
  165.     float d=1.0;
  166.     for(int n=0; n<=MAX_ITER; ++n)
  167.     {
  168.         r = length(v);
  169.         if(r>BAILOUT) break;
  170.  
  171.         d *= pow(r, 7.)*8.+1.;
  172.         float zr2 = dot(v, v);
  173.         float zq2 = dot(v.xz,v.xz);
  174.         float izr2 = 1.0/zr2;
  175.         float izq2 = 1.0/zq2;
  176.        
  177.         vec4 k2 = vec4( izr2*v.y*v.y, izr2*zq2, izq2*v.z*v.z, izq2*v.x*v.x );
  178.         vec4 k4 = k2*k2;
  179.         vec4 k6 = k4*k2;
  180.         vec4 k8 = k4*k4;
  181.        
  182.         float ko = izr2*v.y*sqrt(zq2);
  183.         float ki = izq2*v.z*v.x;
  184.  
  185.         float cozo8 = k8.x + k8.y - 28.0*k6.x*k2.y - 28.0*k2.x*k6.y + 68.0*k4.y*k4.x;
  186.         float cozi8 = k8.z + k8.w - 28.0*k6.z*k2.w - 28.0*k2.z*k6.w + 68.0*k4.w*k4.z;
  187.         float sizo8 = 8.0*ko*(k6.x - k6.y - 7.0*k2.y*k4.x + 7.0*k2.x*k4.y);
  188.         float sizi8 = 8.0*ki*(k6.z - k6.w - 7.0*k2.w*k4.z + 7.0*k2.z*k4.w);
  189.        
  190.         float zr8 = zr2*zr2; zr8 = zr8*zr8;
  191.         //v = zr8*vec3( sizo8*sizi8, cozo8, sizo8*cozi8 );
  192.         v = zr8*vec3( sizo8, cozi8, cozo8 );
  193.        
  194.         //faster (no sqrt) but not really interesting
  195.         //v = zr8*vec3( sizi8, cozi8, cozo8 );
  196.         //v = zr8*vec3( sizi8, cozo8, cozi8 );
  197.  
  198.         v += c*sinTime;
  199.         color = abs(v.x)+abs(v.y)+abs(v.z);
  200.     }
  201.     return .5*log(r)*r/d;
  202. }
  203.  
  204.  
  205. void main( void )
  206. {
  207.     vec2 pos = (gl_FragCoord.xy - resolution.xy) / resolution.x;
  208.  
  209.     if ( pos.x > 1. || pos.y > 1.)
  210.     {
  211.         gl_FragColor = vec4(0, 0, 0, 1);
  212.         return;
  213.     }
  214.    
  215.  
  216.     float n;
  217.     if (PASS_DIR == 1)
  218.         n = mod(1. + PASS + gl_FragCoord.y + gl_FragCoord.x, NB_PASS);
  219.     else
  220.         n = mod(PASS + gl_FragCoord.y - gl_FragCoord.x, NB_PASS);
  221.    
  222.     if ( n != 0.)
  223.     {
  224.         gl_FragColor = vec4(0, 0, 0, 0); return;
  225.     }
  226.  
  227.     vec3 rayDir = normalize((ZOOM*sinTime)*camDir + pos.x*camSide + pos.y*camCDS);
  228.    
  229.     float detail = (DETAIL/ZOOM)*2.;
  230.     if (detail>.0025) detail = 0.0025;
  231.    
  232.     float m = 1.0;
  233.     float dist = 0.0;
  234.     float total_dist = 0.9;
  235.    
  236.     float rdt = dot(camPos, rayDir);
  237.     float rdr = dot(camPos, camPos) - (1.3);
  238.     float Disc = (rdt*rdt)-rdr;
  239.     float col2 = 0.;
  240.     float col = 0.;
  241.     float color = 0.;
  242.     if (Disc>0.)
  243.     {
  244.         for(int i=0; i<MAX_MARCH; ++i)
  245.         {
  246.             total_dist+=dist;
  247.             dist = mandelbulb(camPos + rayDir * total_dist, color);
  248.             m -= 1./float(MAX_MARCH);
  249.            
  250.             if(dist<detail || total_dist>MAX_DIST) break;
  251.         }
  252.         col2 = m*(2.-total_dist)*.5;
  253.         col = m*color*.4;
  254.        
  255.     }    
  256.     if (total_dist>MAX_DIST) col = 0.;
  257.  
  258.     gl_FragColor = vec4(col, col2, col2, 1.);
  259. }    
  260.  
  261. ]]
  262.     return source
  263. end
  264.  
  265. function Scene:vertexShader()
  266.     local source =
  267. [[
  268. attribute vec4 position;
  269. void main()
  270. {
  271.     gl_Position = position;
  272. }
  273. ]]
  274.     return source
  275. end
  276.  
  277.  
  278. --# Touches
  279. --                   Touch Handling                 --
  280. ------------------------------------------------------
  281.    
  282. function touched(touch)
  283.     local sh = scene.surface.shader
  284.     local state = touch.state
  285.     local touches = touches
  286.     local deltaX = touch.deltaX
  287.     local deltaY = touch.deltaY
  288.  
  289.    
  290.    
  291.     if state == ENDED then
  292.         nbTouches = nbTouches - 1
  293.         touches[touch.id] = nil
  294.         if not zooming then T_ENDED = true end
  295.     else
  296.         if state == BEGAN then
  297.             nbTouches = nbTouches + 1
  298.             if not zooming then T_BEGAN = true end
  299.         end
  300.        
  301.         touches[touch.id] = touch
  302.     end
  303.    
  304.     if touch.tapCount == 2 and state == ENDED then
  305.         zoomDir = -zoomDir
  306.     end
  307.    
  308.     if touch.tapCount == 3 and state == ENDED then
  309.         if zooming then
  310.             zooming = false
  311.             T_ENDED = true
  312.         else
  313.             zooming = true
  314.             T_BEGAN = true
  315.             T_ENDED = false
  316.         end
  317.     end
  318.    
  319.     local cos = math.cos
  320.     local sin = math.sin
  321.     local pi = math.pi
  322.    
  323.    
  324.     if nbTouches == 1 then
  325.         t.x = t.x + ((deltaX/WIDTH)*pi*2)/(t.z)
  326.         t.y = t.y + ((deltaY/HEIGHT)*pi*2)/(t.z)
  327.    
  328.         if t.y>=pi/2 then t.y = t.y - (deltaY/HEIGHT)*pi*2 end
  329.         if t.y<=-pi/2 then t.y = t.y - (deltaY/HEIGHT)*pi*2 end
  330.        
  331.         local camPos = vec3(cos(t.y)*cos(t.x), sin(t.y), cos(t.y)*sin(t.x))*2
  332.         local camUp = vec3(0., 1., 0.)
  333.         local camTarget = vec3(0., 0., 0.)
  334.         local camDir = (camTarget-camPos):normalize()
  335.         local camSide = camDir:cross(camUp):normalize()
  336.         local camCDS = camDir:cross(camSide)
  337.        
  338.         sh.camPos = camPos
  339.         sh.camSide = camSide
  340.         sh.camDir = camDir
  341.         sh.camCDS = camCDS
  342.     end
  343.    
  344. -- Handle pinch to zoom
  345.     if nbTouches == 2 then
  346.         local newPt = {}
  347.         local lastPt = {}
  348.         local ins = table.insert  
  349.         for _, p in pairs(touches) do
  350.             local px = p.x
  351.             local py = p.y
  352.             ins(newPt, vec2(px, py))
  353.             if state == BEGAN then
  354.                 ins(lastPt, vec2(px, py))
  355.             else
  356.                 ins(lastPt, vec2(px - p.deltaX, py - p.deltaY))
  357.             end
  358.         end
  359.  
  360.         local delta = lastPt[1]:dist(lastPt[2]) - newPt[1]:dist(newPt[2])
  361.         t.z = t.z - delta/(200/t.z)
  362.         if t.z < .1 then t.z = .1 end
  363.     end
  364.    
  365.    
  366.     sh.ZOOM = t.z
  367. end
  368. --# Backup
  369. --[[
  370. -- http://blog.hvidtfeldts.net/index.php/2011/11/distance-estimated-3d-fractals-vi-the-mandelbox/
  371. #define MR2 .01
  372. #define SCALE -2.
  373. #define C1 abs(SCALE-1.)
  374. #define C2 pow(abs(SCALE), float(1-MAX_ITER))
  375. #define SCALE_VEC vec4(SCALE/MR2, SCALE/MR2, SCALE/MR2, abs(SCALE)/MR2)
  376.  
  377. float mandelbox(vec3 position, inout float color)
  378. {
  379.     vec4 p = vec4(position.xyz, 1.0);
  380.     vec4 p0 = p;
  381.     float n;
  382.     for (int i = 0; i < MAX_ITER; i++)
  383.     {
  384.         p.xyz = clamp(p.xyz, -1.0, 1.0) * 2.0 - p.xyz;
  385.         n = dot(p.xyz, p.xyz);
  386.         p *= max(MR2/n, MR2);
  387.         p = p*SCALE_VEC + p0;  
  388.     }
  389.     return sqrt(n) / p.w;
  390. }
  391.  
  392. --  slightly faster but also inacurate
  393. --  http://www.iquilezles.org/www/articles/mandelbulb/mandelbulb.htm
  394. float fastMandelbulb(vec3 p)
  395. {
  396.     vec3 v = p;
  397.     vec3 c = v;
  398.  
  399.     float r=0.0;
  400.     float d=1.0;
  401.     for(int n=0; n<=MAX_ITER; ++n)
  402.     {
  403.         r = length(v);
  404.         if(r>BAILOUT) break;
  405.        
  406.         d *= pow(r, 7.)*8.+1.;
  407.  
  408.         float x = v.x; float x2 = x*x; float x4 = x2*x2;
  409.         float y = v.y; float y2 = y*y; float y4 = y2*y2;
  410.         float z = v.z; float z2 = z*z; float z4 = z2*z2;
  411.    
  412.         float k3 = x2 + z2;
  413.         float k2 = inversesqrt( pow(k3, 7.) );
  414.         float k1 = x4 + y4 + z4 - 6.0*y2*z2 - 6.0*x2*y2 + 2.0*z2*x2;
  415.         float k4 = x2 - y2 + z2;
  416.    
  417.         v.x = 64.0*x*y*z*(x2-z2)*k4*(x4-6.0*x2*z2+z4)*k1*k2;
  418.         v.y = -16.0*y2*k3*k4*k4 + k1*k1;
  419.         v.z = -8.0*y*k4*(x4*x4 - 28.0*x4*x2*z2 + 70.0*x4*z4 - 28.0*x2*z2*z4 + z4*z4)*k1*k2;  
  420.    
  421.         v += c;
  422.        
  423.     }
  424.     return .5*log(r)*r/d;
  425. }
  426. ]]
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top