Welcome to Fractal Forums

Fractal Software => Programming => Topic started by: ker2x on July 27, 2011, 05:34:32 PM




Title: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 27, 2011, 05:34:32 PM
I'm willing to play with the mandelbulb with code i actually understand (no DE stuff or raymarching or anything).
What would be an very simple (possibly short) code to display a mandelbulb please ?

something eventually structured like this :
for x
  for y
    for z
      iterate
    end
  end
end

thank you :)

edit : if it can be structured like this. what is the code of "iterate" ? :)

--
Keru


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: eiffie on July 27, 2011, 07:42:25 PM
This is NOT the way you want to render a mandelbulb (raymarching and DE actually make it easier).
But since you ask I will see if I remember it off the top of my head.
Replace iterate with:

nx=x
ny=y
nz=z
p=8.0 //order of the bulb
r=sqrt(x*x+y*y+z*z)
iter=0
while iter<MAX_ITERATIONS && r<2.0
  th=atan(y,x)*p
  ph=asin(z/r)*p
  r2p=pow(r,p)
  nx=r2p*cos(ph)*cos(th)+x
  ny=r2p*cos(ph)*sin(th)+y
  nz=r2p*sin(ph)+z
  r=sqrt(x*x+y*y+z*z)
  iter=iter+1
end while
if(iter==MAX_ITERATIONS)then you are "inside" the bulb
else you are "outside" the bulb

Now you have to turn your x,y,z coords into 2d screen space, find the normal at each point and color accordingly. This method will be extremely slow.

CAUTION: I may have missed something here as well. Hopefully someone will catch it.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 27, 2011, 09:28:42 PM
This is NOT the way you want to render a mandelbulb (raymarching and DE actually make it easier).
But since you ask I will see if I remember it off the top of my head.

Because :
- i'm much better at understanding code than formula
- i have some idea about doing "something" with that, but i needed to understand that mandelbulb formula  (and without all the stuff that is not part of the formula (DE, optimisation, etc)) :)

thank you very much :)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 27, 2011, 10:19:50 PM
th=atan(y,x)*p is th=atan(y/x)*p, isn't it ?


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 27, 2011, 11:49:26 PM
beside the typo stated above and some easily spotted confusion between x/y/z and nx/ny/nz, i can say that the code is correct.
My very first experiment at "something" that have 2 name "FlowaBulb" and "DustBulb".
Not sure yet.

Thoses who know my previous experiments can easily guess what i'm trying to do.
And, yes, it's so slow that it hurts  :sad1:

(http://fractals.s3.amazonaws.com/flowabulb/flowabulb.jpg)

Thank you again :)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 27, 2011, 11:55:31 PM
later ...
Yes, a LOT of feature are missing about color, saturation, contrast, brightness, lightning, you-name-it!
It no's crashing and it have a mandelbulb shape, it's not that bad then ;D

(http://fractals.s3.amazonaws.com/flowabulb/flowabulb-2.jpg)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: eiffie on July 28, 2011, 05:49:58 PM
Good you caught that typo.
I assume you are already ray-marching thru z until you hit the bulb so why not add DE like this:
dr=1.0
inside iterate:
dr=dr*p*pow(r,p-1.0)+1.0
after iterate advance z by 0.5*log(r)*r/dr

It will greatly increase the speed and make experimenting with coloring much more enjoyable.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 09:38:00 AM
Good you caught that typo.
I assume you are already ray-marching thru z until you hit the bulb so why not add DE like this:
dr=1.0
inside iterate:
dr=dr*p*pow(r,p-1.0)+1.0
after iterate advance z by 0.5*log(r)*r/dr

It will greatly increase the speed and make experimenting with coloring much more enjoyable.

I'm rendering 3D buddhabrot (buddhabulb ? i'm tired of mistyping "buddha", that why i call it FlowaBulb  ;D ) and not doing raymarching at all.
However, i'll probably use DE sooner or later, so thank you for this formula :)

For now my main problem is that i'm not happy with the mandelbulb formula and the "trajectory" of the plots.  :sad1:
Simply said : no orbits, just lines.  :'(

Something is wrong here, and i'm planning to find it :)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 11:01:20 AM
Something is wrong here, and i'm planning to find it :)

Found it, and it was in my code.
Shame on me  :'(


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 11:37:17 AM
And i think to myself ... What a wonderfull wooooooorld !  :whistle2:

(http://fractals.s3.amazonaws.com/flowabulb/Flowabulb-3.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 11:42:46 AM
(http://fractals.s3.amazonaws.com/flowabulb/Flowabulb-4.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: cKleinhuis on July 29, 2011, 12:12:12 PM
the 3d buddha is emerges ;)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 12:21:15 PM
the 3d buddha is emerges ;)

Yes it is ! :love:
The holy-holy-grail  :angel1:


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: A Noniem on July 29, 2011, 12:38:50 PM
the 3d buddha is emerges ;)

Yes it is ! :love:
The holy-holy-grail  :angel1:

There are more efficient ways to get the holy grail though.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on July 29, 2011, 12:50:21 PM
the 3d buddha is emerges ;)

Yes it is ! :love:
The holy-holy-grail  :angel1:

There are more efficient ways to get the holy grail though.

I'm sure of it  ;D
But, to me, the process is as important as the result itself, i want to do it myself (instead of using someone else program) and i start with code i can understand and write then modify to optimize it.
(an OpenCL version is, of course, planned)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 01, 2011, 08:50:19 AM
the 3d buddha is emerges ;)

Done  ;D
Window binary and source code : http://fractals.s3.amazonaws.com/flowabulb/voxelflowabrot-0.2.zip

A video of the program :
http://www.youtube.com/watch?v=lGLcslZqE8c


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 02, 2011, 09:49:59 PM
voxelflowabrot-0.4 : http://fractals.s3.amazonaws.com/flowabulb/voxelflowabrot-0.4.zip

Lot of code refactoring and some openGL tuning (including antialiasing) :)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 07, 2011, 10:12:21 PM
Good you caught that typo.
I assume you are already ray-marching thru z until you hit the bulb so why not add DE like this:
dr=1.0
inside iterate:
dr=dr*p*pow(r,p-1.0)+1.0
after iterate advance z by 0.5*log(r)*r/dr

It will greatly increase the speed and make experimenting with coloring much more enjoyable.

It doesn't work :(
i coded what i understood of the raymarching thingy.
If i advance by 0.1 instead of your formula, i have something.
if i use 0.5*log(r)*r/dr; i have nothing.

Can you take a look at this very ugly code and help please ? :)

Code:
final int MAXITER = 16;
final int MAXSTEP = 255;
final float p=8.0;
final color white = color(255);

float[][] pts = new float[MAXITER+1][3];
int count = 0;
float x,y,z;


void setup() {
  size(800,800,P2D);
  frameRate(1000);
  background(0);
  stroke(255);
}

void draw() {
  loadPixels();
  count++;
  if(count > 10000) {
    count=0;
    randomSeed(millis());
  }
  for(int i = 0; i < 1000; i++) {
  x = random(-1.5,1.5);
  y = random(-1.5,1.5);
  z = -4.0;
  float dr = 1.0;
  int step =0;

  for(step = 0; step < MAXSTEP; step++) {
  int iter = 0;
  float r = 0.0;
  float nx = x;
  float ny = y;
  float nz = z;
  r=sqrt(x*x+y*y+z*z);
  float th=atan(y/x)*p;
  float ph=asin(z/r)*p;
  float u,v;

    while(iter < MAXITER && r<2.0  ) {
      float r2p = pow(r,p);
      th=atan(ny/nx)*p;
      ph=asin(nz/r)*p;
      nx=r2p*cos(ph)*cos(th)+x;
      ny=r2p*cos(ph)*sin(th)+y;
      nz=r2p*sin(ph)+z;
      r=sqrt(nx*nx+ny*ny+nz*nz);
      dr=dr*p*pow(r,p-1.0)+1.0;
      iter++;
    }
    //println(dr);
    if(r<2.0) {
        u =  x * 6.0 / (z + 4.0);
        v = y  * 6.0 / (z + 4.0);
        u = (2.0 + u) / 4.0 * width;
        v = (2.0 + v) / 4.0 * height;
        if(u > 0 && u < width && v > 0 && v < height) {
          pixels[(int)((int)u + (int)v * width)] = color(step*1,step*1,step*1);
        }
        break;
    } else {
      step++;
      z+=0.1;//*log(r)*r/dr;
    }
  }
  } 
  updatePixels();


 


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 07, 2011, 10:23:26 PM
i just noticed that the mandelbulb formula in fragmentarium was very easy to understand and i'll try to learn from it :)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 07, 2011, 10:41:42 PM
My problem is that dr quickly become == Double.POSITIVE_INFINITY


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Syntopia on August 08, 2011, 12:16:00 AM
The 'dr'-value must be reset inside the MAXSTEP loop, just like 'r'.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 08, 2011, 01:03:21 AM
The 'dr'-value must be reset inside the MAXSTEP loop, just like 'r'.

Well, it still doesn't work  :'(
But at least one insane error is patched  ;D

here is the current code :

Code:
final int MAXITER = 16;
final int MAXSTEP = 255;
final float p=8.0;
final color white = color(255);

float[][] pts = new float[MAXITER+1][3];
int count = 0;
float x,y,z;


void setup() {
  size(800,800,P2D);
  frameRate(1000);
  background(0);
  stroke(255);
}

void draw() {
  loadPixels();
  count++;
  if(count > 10000) {
    count=0;
    randomSeed(millis());
  }
  for(int i = 0; i < 1000; i++) {
  x = random(-1.5,1.5);
  y = random(-1.5,1.5);
  z = -4.0;
 
  int step =0;

  for(step = 0; step < MAXSTEP; step++) {
  int iter = 0;
  float r = 0.0;
  float dr = 1.0;
  float nx = x;
  float ny = y;
  float nz = z;
  r=sqrt(x*x+y*y+z*z);
  float th=atan(y/x)*p;
  float ph=asin(z/r)*p;
  float u,v;
 
    while(iter < MAXITER /*&& r<2.0*/  ) {
      float r2p = pow(r,p);
      th=atan2(ny,nx)*p;
      ph=asin(nz/r)*p;
      nx=r2p*cos(ph)*cos(th)+x;
      ny=r2p*cos(ph)*sin(th)+y;
      nz=r2p*sin(ph)+z;
      r=sqrt(nx*nx+ny*ny+nz*nz);
      dr=dr*p*pow(r,p-1.0)+1.0; 
      iter++;
    }
   
    if(r<2.0) {
        println(dr);
        u =  x * 6.0 / (z + 4.0);
        v = y  * 6.0 / (z + 4.0);
        u = (2.0 + u) / 4.0 * width;
        v = (2.0 + v) / 4.0 * height;
        if(u > 0 && u < width && v > 0 && v < height) {
          pixels[(int)((int)u + (int)v * width)] = color(step*1,step*1,step*1);
        }
        break;
    } else {
      step++;
      z+=0.1;
      z+=0.5*log(r)*r/dr; //<-nothing
    }
  }
  } 
  updatePixels();




the output that display dr whrn r < 2.0 :
11.36559
3.330166
12.572722
10.215517
5.687963
28.261217
43.640415
3.3310628
3.3878212
13.518621
3.347372
10.360928
7.386033
...


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 08, 2011, 01:15:08 AM
Well, obviously i should display println(0.5*log(r)*r/dr); to see how big was supposed to be my last step :

4.1891032E-4
0.0011521813
5.504626E-4
-0.003734893
-0.051313702
1.649025E-4
-0.015488651
2.312548E-6
-0.0359119
-0.013137315
-0.0013213182
-0.036753275
-1.0157118E-4
-3.4222467E-7
-0.0076081255
-0.014232793
-0.03867302
-2.776414E-4
-8.763797E-6
-0.039671708
-0.0022190188
9.5214637E-4
-6.9133566E-5
-0.029464567
-2.9889583E-7
-0.0017719215
-0.027600588
-0.011584057
-0.00846173
-6.32731E-5


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 08, 2011, 01:20:50 AM
if i replace :
if(r<2.0)
by :
if(0.5*log(r)*r/dr > -10e-20 && 0.5*log(r)*r/dr < 10e-20)
i have a correct something that look like a buddhabrot.


but i still can't do z+=0.5*log(r)*r/dr;


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: eiffie on August 09, 2011, 05:31:23 PM
One problem I see with the code is the order you are calculating r and dr. Switch them.
dr=dr*...   //you want to calc using the old r
then
r=sqrt(...

also typically we bail at r<2.0 so I am not sure this works well for your purpose.
I was confusing myself there! Glad it works for you.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 09, 2011, 07:29:56 PM
It works \o/
Thank you  ;D

(http://fractals.s3.amazonaws.com/PMandelbulb/PMandelbulb-1.jpg)

Code:
final int MAXITER = 16;
final int MAXSTEP = 255;
final float p=8.0;
final color white = color(255);

float[][] pts = new float[MAXITER+1][3];
int count = 0;
float x,y,z;


void setup() {
  size(800,800,P2D);
  frameRate(1000);
  background(0);
  stroke(255);
}

void draw() {
  loadPixels();
  count++;
  if(count > 10000) {
    count=0;
    randomSeed(millis());
  }
  for(int i = 0; i < 10000; i++) {
  x = random(-1.5,1.5);
  y = random(-1.5,1.5);
  z = -4.0;
  
  int step =0;

  for(step = 0; step < MAXSTEP && z < 4.0; step++) {
  int iter = 0;
  float r = 0.0;
  float dr = 1.0;
  float nx = x;
  float ny = y;
  float nz = z;
  r=sqrt(x*x+y*y+z*z);
  float th=atan(y/x)*p;
  float ph=asin(z/r)*p;
  float u,v;
  
    while(iter < MAXITER && r<2.0  ) {
      float r2p = pow(r,p);
      th=atan2(ny,nx)*p;
      ph=asin(nz/r)*p;
      nx=r2p*cos(ph)*cos(th)+x;
      ny=r2p*cos(ph)*sin(th)+y;
      nz=r2p*sin(ph)+z;
      dr=dr*p*pow(r,p-1.0)+1.0;  
      r=sqrt(nx*nx+ny*ny+nz*nz);
      iter++;
    }
    
    if(0.5*log(r)*r/dr < 0.00001) {
        
        u =  x * 6.0 / (z + 4.0);
        v = y  * 6.0 / (z + 4.0);
        u = (2.0 + u) / 4.0 * width;
        v = (2.0 + v) / 4.0 * height;
        if(u > 0 && u < width && v > 0 && v < height) {
          pixels[(int)((int)u + (int)v * width)] = color(step*1,step*1,step*1);
        }
        break;
    } else {
      step++;
      z+=0.5*log(r)*r/dr;
    }
  }
  }  
  updatePixels();
}  

  



Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: A Noniem on August 09, 2011, 08:23:13 PM
If I were you i'd make a ray tracer (if you know how it works, beginning from scratch is hard). It's more difficult, but the results are a lot nicer and the rendering time is a lot less.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 10, 2011, 12:56:46 PM
If I were you i'd make a ray tracer (if you know how it works, beginning from scratch is hard). It's more difficult, but the results are a lot nicer and the rendering time is a lot less.

Step by step, i want to understand what i'm doing.
I took a few hours to translate some code to OpenCL, not yet optimized but it's much much faster already  ;D

However, i will keep the Monte Carlo method, i like it  :embarrass:
I'm not good enough to write the best fractal software, and i don't have enough time for that anyway, i want to learn and have fun.

Yes, i'll write a raytracer, with openCL.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 10, 2011, 11:01:12 PM
some improvments  ;D

It's much nicer when the fractal is white and more step = more shadow   :embarrass:
(instead of a black fractal with color = number of step)

(http://fractals.s3.amazonaws.com/mandelbulb/PMandelbulb_0_3-1.jpg)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 10, 2011, 11:12:46 PM
and some fake lightning colors based on X,Y,Z position

(http://fractals.s3.amazonaws.com/mandelbulb/PMandelbulb_0_3-2.jpg)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 10, 2011, 11:24:00 PM
Now i'm wondering...

what is the next logical feature to add ?


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: marius on August 10, 2011, 11:33:22 PM
Now i'm wondering...

what is the next logical feature to add ?

stereoscopy!


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on August 10, 2011, 11:55:20 PM
Ho! wow ... i have NVidia's 3D Vision google and i never tought to test it on my 3D flowabulb  (it's openGL, so it should works directly without problem) :o


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: A Noniem on August 11, 2011, 12:46:18 AM
That would be a truly awesome feature  :dink:
Images look nice btw, they are getting nicer every day.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 22, 2012, 06:55:26 PM
Hi gang;

I too, like Ker2X, am trying to learn how to generate the Mandelbulb, through studying and learning source code (I understand that much better than algorithms).

I have been working with the previously posted code and understanding how it works, as well as adapting it for my own purposes.

I would love any help and suggestions on how to continue developing this further. Building a raytracer would be an amazing experience but that is far beyond my capabilities (I'm primarily an artist and only secondarily a programmer - the two don't mix!).

The first thing I did was take ker2X's great code and try to optimize it by removing the random sampling part and instead convert it to a pixel by pixel ray marcher.

 
Code:
 for(y = 0; y < Y; y++) 
  for(x = 0; x < X; x++) {
   xx = 2.0* ((float)x/(float)X) -1.0;
   yy = 2.0* ((float)y/(float)Y) -1.0;
   zz = -4.0;

In other words, march a ray from every screen pixel and draw the fractal that way. Although it is far faster (you don't end up using duplicate rays), it presents some problems which I can't figure out:

(http://www.richardrosenman.com/storage/mandelbulb_xy_speckles.jpg)

This is a render of the MB using 2 iterations only and it shows these black speckles. They are present in any iteration count but this one is the clearest to see. I think this is because those points are not being rendered but I don't understand why since a ray is being marched from every pixel. In theory, it shouldn't miss any points.

I had a hunch it was something to do with the bounding box:

Code:
 
xx = 2.0* ((float)x/(float)X) -1.0;
yy = 2.0* ((float)y/(float)Y) -1.0;

So I started experimenting with a larger one to see if that was the problem. For the next image, I tried:

Code:
 
xx = 4.0* ((float)x/(float)X) -2.0;
yy = 4.0* ((float)y/(float)Y) -2.0;

And then:

Code:
 
xx = 8.0* ((float)x/(float)X) -4.0;
yy = 8.0* ((float)y/(float)Y) -4.0;

(http://www.richardrosenman.com/storage/mandelbulb_xy_bb.jpg)

So it looks like those are spaces in between the pixels that I'm tracing? Is this the cause of the speckling I'm getting in the first image? I tried the opposite and minimized the bounding box to a smaller than usual value and the black speckles became fewer.

Anyway, I suppose my first question is: Am I doing this the right way? If I want to trace a ray from each pixel to draw a clean MB? If so, why am I getting these artifacts?

Thanks in advance for any suggestions and help. I am really looking forward to learning how to do this with some of your much appreciated help!

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on March 23, 2012, 08:03:39 AM
a point is black if the ray stop before being close enough to a surface.
(or if it's detected outside of the mandelbulb set, of course)


try with a higher value of maxstep ?
AND/OR
if(0.5*log(r)*r/dr < 0.00001) <- try with 0.001 ?

(i don't remember why the 0.5 ratio but, if i remember correctly, it's a bad idea to change it)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on March 23, 2012, 08:10:08 AM
btw, that's why i like montecarlo method. It's very simple and it eventually converge to an ideal.  ;D
(some code is missing, i should average/smooth/whatever the value of a pixel when many rays it the same pixel)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 23, 2012, 04:15:10 PM
a point is black if the ray stop before being close enough to a surface.
(or if it's detected outside of the mandelbulb set, of course)


try with a higher value of maxstep ?
AND/OR
if(0.5*log(r)*r/dr < 0.00001) <- try with 0.001 ?

(i don't remember why the 0.5 ratio but, if i remember correctly, it's a bad idea to change it)

Hi Ker2x;

Yes, I've tried playing with that value and although the accuracy varies it still produces the black speckles. With the Monte Carlo it doesn't produce the artifacts but it takes forever to render and never clean enough unless you let it run indefinitely.

I'm sampling a ray per pixel so there shouldn't be any missed rays.

I wonder if perhaps it has something to do wih my compiler and floating point accuracy? (I've had problems with that before). I guess I am looking for confirmation of whether I was doing that correctly or if there's a better way to do it?

Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: yv3 on March 23, 2012, 10:50:57 PM
Thank you ker2x very much for providing the mandelbulb formula!! My math knowledge is bad and i was looking for something like this a long time. Now i can explore mandelbulbs the first time in my own tool! its like a new era has come :). I never liked mandelbulbs/3d fractals much in the past time, but its something other if you "try" it out by yourself, modifying the formula and adding parameters to it. I changed your algorithm to calculate the color of a specific position like in did it for traditional mandelbrot rendering. It works perfectly for me, i was overwhelmed when the first images appeared on the screen after a half hour of trying around:

(http://yv3.bplaced.net/gallery/yFract/26555.jpg)
[FULL SIZE (http://yv3.bplaced.net/gallery/yFract/26555.jpg)]

(http://yv3.bplaced.net/gallery/yFract/26556.jpg)
[FULL SIZE (http://yv3.bplaced.net/gallery/yFract/26556.jpg)]
Yeah i found it :)

(http://yv3.bplaced.net/gallery/yFract/26557.jpg)
[FULL SIZE (http://yv3.bplaced.net/gallery/yFract/26557.jpg)]

I found the formula of god, it produces models of fairy women without arms :)

The only problem is, its very slow compared to the calculation of traditional 2d fractals in my tool. Anyone has an idea how to speed up my code?

Code:
void yFractal::GetFractalColor999() 
{
static float x, y, z, r, dr, nx, ny, nz, th, ph, r2p, cr1, cr2, cr4, max_z, mag;
static int iter, step;

cr1 = float(m_CustomRange1);
cr2 = float(m_CustomRange2);
max_z = float(m_CustomRange3); 
cr4 = float(m_CustomRange4);
mag = float(m_Magnitude)/1000.0f;

x = float(m_StartX);
y = float(m_StartY);
z = -max_z;

for(step=0; step<m_Iterations && z<max_z; step++)
{
iter=0;
r=0.0f;
dr=1.0f;
nx=x;
ny=y;
nz=z;
r=sqrtf(x*x + y*y + z*z);
th=atanf(y/x) * cr2;
ph=asinf(z/r) * cr2;

while(iter<cr1 && r<4.0f)
{
r2p=powf(r, cr2);

th=atan2f(ny, nx) * cr2;
ph=asinf(nz/r) * cr2;

nx=r2p*cosf(ph)*cosf(th) + x;
ny=r2p*cosf(ph)*sinf(th) + y;
nz=r2p*sinf(ph) + z;

dr=dr*cr2*powf(r, cr2-1.0f) + 1.0f; 
r=sqrtf(nx*nx + ny*ny + nz*nz);

iter++;
}

if(0.001f*logf(r)*r/dr < mag)
{
m_C=int( float(step) * m_ColorPerIteration ); // Return color index from range 0 to (m_NumColors-1)
return;
}
else
{
step++;
z+=cr4*logf(r)*r/dr;
}

} //for(step=0; step<m_Iterations && z<max_z; step++)

m_C=0;
}

HELP


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on March 24, 2012, 01:11:08 AM
i'm glad it help more than myself  ;D


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 25, 2012, 08:08:52 AM
That's a very nice result, could you post your new code please? I wanted to wrap my head around doing something like that. I made a Mandelbulb code in Processing recently but it just is testing every point in a voxel space. Here's my code:

Code:
float xmin = -2;
float ymin = -2;
float zmin = -2;
float wh = 4;
int maxIterations = 6;
int power = 8;
int screenSize = 200;

void setup() {
  size(screenSize, screenSize, P3D);
  noStroke();
  noLoop();
}

void draw() {
  background(255);
  translate(0, screenSize/2, 0);
  rotateX(-HALF_PI);
  translate(0, -screenSize/2, -screenSize/2);
  float xmax = xmin+wh;
  float ymax = ymin+wh;
  float zmax = zmin+wh;
  float dx = (xmax-xmin)/screenSize;
  float dy = (ymax-ymin)/screenSize;
  float dz = (zmax-zmin)/screenSize;
  int count = 0;
  float x = xmin;
  for (int i = 0; i < screenSize; i++) {
    float y = ymin;
    for (int j = 0; j < screenSize; j++) {
      float z = zmin;
      for (int k = 0; k < screenSize; k++) {
        float nx = x;
        float ny = y;
        float nz = z;
        int n = 0;
        while (n < maxIterations) {
          float rad = pow(sqrt(nx*nx+ny*ny+nz*nz), power);
          float theta = atan2(sqrt(nx*nx+ny*ny), nz)*power;
          float phi = atan2(ny, nx)*power;
          nx = sin(theta)*cos(phi)*rad+x;
          ny = sin(theta)*sin(phi)*rad+y;
          nz = cos(theta)*rad+z;
          if (nx*nx+ny*ny+nz*nz > 16) break;
          n++;
        }
        if (n == maxIterations) {
          float distE = sqrt(x*x+y*y+z*z);
          float cr = 98*(abs(x)+distE);
          float cg = 98*(abs(y)+distE);
          float cb = 98*(abs(z)+distE);
          fill(cr, cg, cb);
          translate(i, j, k);
          box(1);
          translate(-i, -j, -k);
        }
        z += dz;
      }
      y += dy;
    }
    x += dx;
    println((float(count)/screenSize*100)+"%");
    count++;
  }
  println("Time: "+millis());
  saveFrame("result.png");
}


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 27, 2012, 04:11:48 AM
My bad, I was looking at the post more carefully and realized your code for the black one could easily become the white one by changing the coloring to: color(255-step);

I was wondering how you figured out how to get the 3D points to work with pixels[]. My code goes through all the points in a bounding box so z changes. I used to just use screenX and screenY like but it left me with visual artifacts.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 27, 2012, 04:25:12 AM
My bad, I was looking at the post more carefully and realized your code for the black one could easily become the white one by changing the coloring to: color(255-step);

I was wondering how you figured out how to get the 3D points to work with pixels[]. My code goes through all the points in a bounding box so z changes. I used to just use screenX and screenY like but it left me with visual artifacts.

I would like to know this too since I too am getting artifacts when I run thought the pixels. I am comparing my renders to Tom Beddard's and his are perfectly clean, while mine are very noisy.

-Richard


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on March 27, 2012, 04:29:38 PM
now it may be a good idea to learn about raymarching  ;D

http://www.fractalforums.com/general-discussion/ray-marching/msg40101/#msg40101


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 28, 2012, 03:18:31 AM
Hi Ker2x;

I understand the premise of raymarching and (vaguely) the raymarcher in the sample code. It is very similar to Tom's as well but yet produces noise in my images and not in his. This means I must have an error in the code, or Tom uses additional improvement functions which I cannot see.

Here's an example:

(http://www.richardrosenman.com/storage/mb_comparison.jpg)

You can see the results are extremely different. I know Tom's has specularity, light sources, and all that but even without, the surfaces are intact. Mine are not. Any ideas?

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Softology on March 28, 2012, 11:21:13 PM
You can see the results are extremely different. I know Tom's has specularity, light sources, and all that but even without, the surfaces are intact. Mine are not. Any ideas?
-Rich

From what I can tell the noise looks like it comes from a higher iteration count you are using that adds more detail to your image.  The speckled black pixels are most likely due to that pixel's ray happening to take more steps to hit the surface than the neighbours so it gets the darker ambient color (assuming this is how you are shading the surface).  Your image actually shows more detail.

Try oversampling.  Render each pixel as a group of subpixels averaged.

This test image used no oversampling and shows the noisy surface like your image

(http://farm8.staticflickr.com/7199/7024929015_8b7f3f937c_o.jpg)

and the same image with 3x oversampling (ie 9 rays per pixel)

(http://farm7.staticflickr.com/6211/6878828256_b66fee4117_o.jpg)

and with multiple lights, shadows and specularity

(http://farm8.staticflickr.com/7240/6878861854_4975df09e1_o.jpg)

Chances are your raytracing code is fine and the artifacts/speckles/noise are not coding problems.

Edit: Another idea.  Render your image and just use white for "hit the fractal" and black for "missed".  If the main body is fully white then your raytracing code is definitely correct and the noise comes down to lighting/shading.

Jason.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 29, 2012, 01:55:03 AM
Hi Jason;

First of all, thanks so much for your prompt reply. Secondly, your renders look AMAZING!

I understand what you're saying and I think you may be right but I'm not entirely convinced. I have implemented super sampling and below is a render with 3x3 SS using first 8 iterations and then 3. I still think it's not as clean as yours. How many iterations did you use in your test?

(http://www.richardrosenman.com/storage/mb_ss.jpg)

Now that you see these SS renders, do you think they are correct? Or do you feel they are still noisy?

Once again, I really appreciate your help!

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Softology on March 29, 2012, 02:25:14 AM
I understand what you're saying and I think you may be right but I'm not entirely convinced. I have implemented super sampling and below is a render with 3x3 SS using first 8 iterations and then 3. I still think it's not as clean as yours. How many iterations did you use in your test?

I used 5 iterations for those.

Quote
Now that you see these SS renders, do you think they are correct? Or do you feel they are still noisy?

They look fine to me.  Nothing I would call "noise" and some really nice fine details visible now.  Once you add shadows and colors etc they will really "pop".

I am not sure which of the many Mandelbulb variants that code uses.  http://www.fractalforums.com/theory/summary-of-3d-mandelbrot-set-formulas/ covers a bunch of them.  Basically they all use different sin and cos for the theta and phi and triplex power calculations.

Jason.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Softology on March 29, 2012, 03:18:06 AM
Also, for shading.  Using the step count for ambient occlusion is not the best method.  iq on here (I am sure it was iq, but cannot find the original post now) came up with using orbit traps to fake the shading.  I use the same method and it really does a good "fake" AO that darkens the crevices and nooks and crannies well.

minorbit and maxorbit are user settable values.  for the above renders I used minorbit=0.6 maxorbit=1

before rendering each pixel init smallestorbit to a huge value
smallestorbit:=1e200

during each iteration
 if radius<smallestorbit then smallestorbit:=radius;

after iterations completed
if smallestorbit<minorbit then smallestorbit:=minorbit;
if smallestorbit>maxorbit then smallestorbit:=maxorbit;
smallestorbit:=(smallestorbit-minorbit)/(maxorbit-minorbit);
red:=red*smallestorbit;
green:=green*smallestorbit;
blue:=blue*smallestorbit;

that darkens each RGB pixel value depending on how close the orbit was "trapped" to the origin.

Hopefully that makes enough sense to implement.  You will get much nicer ambient occlusion looking results.

Jason.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 29, 2012, 03:57:57 AM
Jason - thanks so much for all this info.

I will start by maybe trying to match the Mandelbulb variant to yours. So that I can compare more easily. This is the algorithm this one currently uses:

Code:
nx=r2p*cos(ph)*cos(th)+dx;
ny=r2p*cos(ph)*sin(th)+dy;
nz=r2p*sin(ph)+dz;

Then I will try to implement your orbit trap method of shading. One question though:

I understand that to shade, you subtract the step count from the white: (255-step). The ambient occlusion, is secondary algorithm which, in my case, also uses the step value as you pointed out. So am I shading it correctly in using the step value and it's just the secondary AO that requires the orbit trap method or should I be shading it altogether differently? Ie. NOT using steps at all but ONLY AO for ALL shading?

Does this make sense?

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Softology on March 29, 2012, 04:11:25 AM
I understand that to shade, you subtract the step count from the white: (255-step). The ambient occlusion, is secondary algorithm which, in my case, also uses the step value as you pointed out. So am I shading it correctly in using the step value and it's just the secondary AO that requires the orbit trap method or should I be shading it altogether differently? Ie. NOT using steps at all but ONLY AO for ALL shading?

I use the formulas...
(converting cartesian to spherical polar)
radius=sqrt(z.x*z.x+z.y*z.y+z.z*z.z)
theta=arctan2(z.y,z.x)
phi=arcsin(z.z/radius)

(z^p)
radius=power(radius,p)
theta=theta*p
phi=phi*p
z.x=radius*cos(phi)*cos(theta)
z.y=radius*cos(phi)*sin(theta)
z.z=radius*sin(phi)
They seem to look close enough to what you are using.  Posty your full code if you like and I can see what differs from mine.

Step count does not come into coloring/shading at all (it works, but darkens the wrong areas).  For these sort of renders (ambient light only) each pixel is white RGB 255 and the AO calculations darken the pixel after the iteration loop finishes.  Using the orbit trap method nicely darkens the crevices to give it the ambient occlusion look.

Jason.



Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 29, 2012, 04:23:50 AM
Very interesting, Jason.

Here's what I'm working with so far. The AO and SS is from Tom's script. I will give the orbit trap shading a shot tomorrow but in the meantime let me know your thoughts:

Code:
    
    parameter int antialiasing
  <
    minValue:int(1);
    maxValue:int(3);
    defaultValue:int(1);
    description: "The antialiasing level.";
  >;
  
    parameter int size
  <
    minValue:int(100);
    maxValue:int(2048);
    defaultValue:int(200);
    description: "The output size in pixels.";
  >;
  
   parameter float ambientOcclusion
<
minValue:0.0;
maxValue:1.0;
defaultValue:0.8;
description: "Enable fake ambient occlusion factor based on the orbit trap.";
>;
    
    parameter float power
<
minValue:1.0;
maxValue:16.0;
defaultValue:8.0;
description: "Power.";
>;
    
        parameter int MAXITER
<
minValue:1;
maxValue:32;
defaultValue:16;
description: "Iterations";
>;
    
    region generated()
  {
    return region(float4(0, 0, size, size));
  }
    output float4 dst;
    
    
// Calculate the output colour for each input pixel
float4 renderPixel(float2 pixel)
{
    float4 color = float4(0, 0, 0, 0);
    float ao;
    float min_dist = 4.0;
    int MAXSTEP = 255;
    int step = 0;
    float dx = 2.0 * pixel.x / float(size) - 1.0;
    float dy = -2.0 * pixel.y / float(size) + 1.0;
    float dz = -4.0;
                      
                                  
  for (step = 0; step < MAXSTEP && dz < 4.0; step++)
  {
  int iter = 0;
  //float r = 0.0;
  float dr = 1.0;
  float nx = dx;
  float ny = dy;
  float nz = dz;
  float r=sqrt(dx*dx+dy*dy+dz*dz);
  float th=atan(dy/dx)*power;
  float ph=asin(dz/r)*power;
  if (r < min_dist) min_dist = r;
  float u,v;
 
  
      while(iter < MAXITER && r < 2.0  )
      {
      float r2p = pow(r,power);
      th=atan(ny,nx)*power;
      ph=asin(nz/r)*power;
      nx=r2p*cos(ph)*cos(th)+dx;
      ny=r2p*cos(ph)*sin(th)+dy;
      nz=r2p*sin(ph)+dz;
      dr=dr*power*pow(r,power-1.0)+1.0;  
      r=sqrt(nx*nx+ny*ny+nz*nz);
      iter++;  
      }
      
      if (r < min_dist) min_dist = r;
      
        if(0.5*log(r)*r/dr < 0.00001)
        {
        ao = 1.0 - clamp(1.0 - min_dist * min_dist, 0.0, 1.0) * ambientOcclusion;
        //color = (255-step,255-step,255-step,255);
        //dst = float4(255-step,255-step,255-step,255);
        //dst.rgb=float3( float(255-step) / 255.0, float(255-step) / 255.0 , float(255-step) / 255.0);
        //dst.a = 1.0;
        break;
        }
        else
        {
        step++;
        dz+=0.5*log(r)*r/dr;
        }

 
        }
            color = float4( float(255-step) / 255.0, float(255-step) / 255.0 , float(255-step) / 255.0, 1.0);
            ao *= 1.0 - (float(step) / float(MAXSTEP)) * 0.58 * 2.0;
            color.rgb *= ao;

            //return float4( float(255-step) / 255.0, float(255-step) / 255.0 , float(255-step) / 255.0, 1.0);
            return clamp(color, 0.0, 1.0);
    }
    
    

// The main loop
void evaluatePixel()
{
float4 color = float4(0, 0, 0, 0);
        float sampleStep = 1.0 / float(antialiasing);
        float sampleContribution = 1.0 / pow(float(antialiasing), 2.0);    
    
if (antialiasing > 1) {
// Average antialiasing^2 points per pixel
for (float i = 0.0; i < 1.0; i += sampleStep)
for (float j = 0.0; j < 1.0; j += sampleStep)
color += sampleContribution * renderPixel(float2(outCoord().x + i, outCoord().y + j));
} else {
color = renderPixel(outCoord());
}

// Return the final color which is still the background color if we didn't hit anything.
dst = color;
}
    
}




Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on March 29, 2012, 11:56:58 AM
Very interesting, Jason.

Here's what I'm working with so far. The AO and SS is from Tom's script. I will give the orbit trap shading a shot tomorrow but in the meantime let me know your thoughts:

Code:
    <snip>


Ermmm - I would suggest that your bailout is too small. The DE (even the deltaDE) relies on the maths behind divergence to infinity and for that to be more accurate requires a larger bailout e.g. testing x^2+y^2+z^2 against a minimum of 1024 (== magnitude against 32).


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 29, 2012, 06:56:49 PM
I rewrote ker2x's code to pass through a double for loop instead of picking random points and I noticed that the resulting images are asymmetric. My guess is that it has something to do with starting from top to bottom then going left to right. What would be the solution to fixing this?

It may be worth noting that I had a problem that looked like richardrosenman's where the image was divided by visible lines. My solution was to oversample (not only test screen pixels but also "pixels" in between) with the "compact" variable below.

Double for loop code:
Code:
int compact = 4;
int maxIterations = 5;
int power = 8;
int screenSize = 400;
float xmin = -1.5;
float ymin = -1.5;
float zmin = -1.5;
float wh = 3.0;
float toAdd = wh/(screenSize*compact);

void setup() {
  size(screenSize, screenSize, P2D);
  background(0);
  noLoop();
}

void draw() {
  loadPixels();
  float x = xmin;
  for (int i = 0; i < screenSize*compact; i++) {
    float y = ymin;
    for (int j = 0; j < screenSize*compact; j++) {
      float z = zmin;
      for (int step = 255; step > 0 && z < -1*zmin; step--) {
        float dr = 1.0;
        float nx = x;
        float ny = y;
        float nz = z;
        float r = sqrt(x*x+y*y+z*z);
        int n = 0;
        while (n < maxIterations && r < 2) {
          float r2p = pow(r, power);
          float th = atan2(ny, nx)*power;
          float ph = asin(nz/r)*power;
          nx = r2p*cos(ph)*cos(th)+x;
          ny = r2p*cos(ph)*sin(th)+y;
          nz = r2p*sin(ph)+z;
          dr = dr*power*pow(r, power-1)+1;
          r = sqrt(nx*nx+ny*ny+nz*nz);
          n++;
        }
        if (0.5*log(r)*r/dr < 0.00001) {
          float u = x*6/(z+4);
          float v = y*6/(z+4);
          u = (2+u)/4*width;
          v = (2+v)/4*height;
          if (u > 0 && u < width && v > 0 && v < height) {
            pixels[(int)u+(int)v*width] = (step<<16)+(step<<8)+step;
          }
          break;
        }
        else {
          step--;
          z += 0.5*log(r)*r/dr;
        }
      }
      y += toAdd;
    }
    x += toAdd;
    println((float)i/(screenSize*compact)*100+"%");
  }
  updatePixels();
  println("Time: "+millis());
}

Here is an image so far that shows the problem:
(http://i.imgur.com/tthrh.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 29, 2012, 08:32:23 PM
A better image that uses the Mandelbulb code from an earlier post here (ray marching is unchanged). Still the same problem with one side being different than the other unfortunately. Also, is it normal to have such hard shadows at the main ring using this technique?

(http://i.imgur.com/t5aIM.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 29, 2012, 09:55:21 PM
Ermmm - I would suggest that your bailout is too small. The DE (even the deltaDE) relies on the maths behind divergence to infinity and for that to be more accurate requires a larger bailout e.g. testing x^2+y^2+z^2 against a minimum of 1024 (== magnitude against 32).


Hi David!

Thanks for you input - it's very much appreciated!

I assume the bailout value you're speaking of is the 2 in the following loop?

Code:
while(iter < MAXITER && r < 2.0  ) 

You're saying this should be something much larger like 32?

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 29, 2012, 10:20:04 PM
Got it working correctly, didn't realized I was overwriting pixels with the old code. The new code below averages all the pixel values instead, I figured I'd post it incase someone wants to play with it in Processing.

EDIT: I updated this code, it's about 5 times faster
New averaging code:
Code:
int compact = 2;
int maxIterations = 3;
int power = 8;
int screenSize = 800;
float xmin = -1.5;
float ymin = -1.5;
float zmin = -1.5;
float wh = 3;
float toAdd = wh/(screenSize*compact);

void setup() {
  size(screenSize, screenSize, P3D);
  noLoop();
}

void draw() {
  loadPixels();
  float[] pixVals = new float[screenSize*screenSize];
  int[] pixDivs = new int[screenSize*screenSize];
  float x = xmin;
  for (int i = 0; i < screenSize*compact; i++) {
    float y = ymin;
    for (int j = 0; j < screenSize*compact; j++) {
      float z = zmin;
      for (int k = 255; k > 0 && z < -1*zmin; k--) {
        float dr = 1;
        float nx = x;
        float ny = y;
        float nz = z;
        float rad = sqrt(x*x+y*y+z*z);
        int n = 0;
        while (n < maxIterations) {
          float powRad = pow(rad, power);
          float theta = atan2(sqrt(nx*nx+ny*ny), nz)*power;
          float phi = atan2(ny, nx)*power;
          nx = sin(theta)*cos(phi)*powRad+x;
          ny = sin(theta)*sin(phi)*powRad+y;
          nz = cos(theta)*powRad+z;
          dr = dr*power*pow(rad, power-1)+1;
          rad = sqrt(nx*nx+ny*ny+nz*nz);
          if (rad > 4) break;
          n++;
        }
        if (0.5*log(rad)*rad/dr < 0.00001) {
          int pixX = i/compact;
          int pixY = j/compact;
          if (pixX > 0 && pixX < screenSize && pixY > 0 && pixY < screenSize) {
            pixVals[pixX+pixY*screenSize] += k;
            pixDivs[pixX+pixY*screenSize]++;
          }
          break;
        }
        else {
          k--;
          z += 0.5*log(rad)*rad/dr;
        }
      }
      y += toAdd;
    }
    x += toAdd;
    println((float)i/(screenSize*compact)*100+"%");
  }
  for (int i = 0; i < screenSize*screenSize; i++) {
    int val = (int)((float)pixVals[i]/pixDivs[i]);
    pixels[i] = (val<<16)+(val<<8)+val;
  }
  updatePixels();
  println("Time: "+millis());
  saveFrame("result.png");
}

EDIT: I replaced the image here, the new code does shadows nicer
New sample image:
(http://i.imgur.com/Wavxa.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on March 29, 2012, 10:32:37 PM
Hi David!

Thanks for you input - it's very much appreciated!

I assume the bailout value you're speaking of is the 2 in the following loop?

Code:
while(iter < MAXITER && r < 2.0  ) 

You're saying this should be something much larger like 32?

-Rich

Yes - the larger you go the greater the accuracy *but* the greater the number of iterations required to approach the solid to a given distance (unfortunately).


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 30, 2012, 07:32:35 AM
I would really like to rotate my Mandelbulb so that the side that is currently facing the viewer is pointing down. I can't seem to figure out how to do this, any suggestions?


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Softology on March 30, 2012, 08:41:48 AM
Ermmm - I would suggest that your bailout is too small. The DE (even the deltaDE) relies on the maths behind divergence to infinity and for that to be more accurate requires a larger bailout e.g. testing x^2+y^2+z^2 against a minimum of 1024 (== magnitude against 32).

Bailout of 4 is fine for the DE method from this thread.  Larger than 4 tends to smooth out the surface and will lose details.

A better image that uses the Mandelbulb code from an earlier post here (ray marching is unchanged). Still the same problem with one side being different than the other unfortunately. Also, is it normal to have such hard shadows at the main ring using this technique?

You found the cause of this, but try using the fake AO I showed earlier in the thread and you will get some nice shadowing in the nooks and crannies of the surface.  It really helps show the structure.



A speedup tip...  do not bother calculating radius as sqrt(x*x+y*y+z*z).  Just track x*x+y*y+z*z and then for the bailout test use >4 rather than >2.  sqrt calls in any language is a major impact speed wise.

Make sure you scale the DE by half (as you do with the 0.5* in the code - you can drop this to lower than 0.5 or have it as a user option, but 0.5 seems to work fine in most scenarios).  The "epsilon" value 0.00001 in your code can also smooth out the surface.  For my images I had epsilon at 0.0001.  The epsilon should be a settable variable as it does determine how smooth the surface can be.  Once you start zooming in for the ideal "most detail without too much noise" render the epsilon is a major factor.  If the detail is too high and messy raising epsilon (say from 0.00001 to 0.0001) helps.  If the surface is too smooth then decreasing epsilon will bring out finer details.

Also for the log in your DE.  Depending on the language I use the natural log "ln" in that calc and log can be log base 10.  I just tried replacing ln with log10 and it didn't seem to make a difference, but at one point with multiple tests I decided to stick with ln.  In other DE code for other fractals I have usually used the natural log, so maybe that can help too.

I hope those tips help get you guys closer to your "perfect render".

Jason.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: richardrosenman on March 30, 2012, 05:57:16 PM
Thanks for those tips, Jason & David!

I will be working with my code this weekend and adding your suggestions. I have already implemented the orbit trap shading and yes, it is quite a bit nicer than before. Thank you for that! I'll post an example asap. ;)

Can I ask about your light sourcing and specularity? Any good suggestions for code examples / theory for this? I know there must be a ton on here but I'm looking for a *really* simply explanation. Do surface normals need to be calculated for specularity?

Asimes: Yours is coming along nicely too. Let's try to figure out the rotation together as this is something I also need to put in next... Nothing like a couple of newbies (one being an artist who can't think in numbers) trying to figure out computational algebra and trigonometry together... ;)

-Rich


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on March 30, 2012, 10:03:31 PM
Bailout of 4 is fine for the DE method from this thread.  Larger than 4 tends to smooth out the surface and will lose details.



That's simply incorrect unless you're not using enough iterations to actually reach a consistent DE value as the solid surface - of course if you're using a particular iteration level as the solid surface then that's a different matter but will never give the consistent detail that using the DE as the solid threshold will achieve.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on March 30, 2012, 10:18:19 PM

Can I ask about your light sourcing and specularity? Any good suggestions for code examples / theory for this? I know there must be a ton on here but I'm looking for a *really* simply explanation. Do surface normals need to be calculated for specularity?


Normals are required both for diffuse and specular if implementing such....the guy to ask about lighting is lycium:

http://www.fractalforums.com/index.php?action=profile;u=87

He's always correcting me anyway (my textbooks are a little old).


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on March 30, 2012, 10:26:02 PM
That's simply incorrect unless you're not using enough iterations to actually reach a consistent DE value as the solid surface - of course if you're using a particular iteration level as the solid surface then that's a different matter but will never give the consistent detail that using the DE as the solid threshold will achieve.

Just to add that to get more detail *and* more accuracy even when using a given iteration boundary as the "solid" surface then it's still better to increase the bailout but to keep the detail you have to increase the "solid" iteration level appropriately.
This means that for z^2+c to use a bailout of 16 (for sqrt(x^2+y^2+z^2) compared to using 2 then you need to increase the surface iteration count by just 2 since 1 extra iteration is required for a bailout of 4 (==2^2), and 2 for 16 (==(2^2)^2), 3 for 64 etc. - so for the suggestion I gave (32) then increasing the surface iteration threshold by 3 would actually result in more detail *and* more accurate DE at the cost of around 3 iterations per loop.


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: Syntopia on March 31, 2012, 01:21:09 AM
Can I ask about your light sourcing and specularity? Any good suggestions for code examples / theory for this? I know there must be a ton on here but I'm looking for a *really* simply explanation. Do surface normals need to be calculated for specularity?

The Phong model is very common and is probably a good staring point: http://en.wikipedia.org/wiki/Phong_reflection_model


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on March 31, 2012, 04:35:27 PM
Softology, mixing the orbit color with the ray marcher looks great, thanks.

I'm beginning to think that my sketch is just not set up for rotation. The part of the sketch that still somewhat alien to me is the "dr" part. However, it seems to only be affected by 'z', maybe if I had it be affected by 'y' it would give me a top down point of view but I don't know about arbitrary rotation. Any suggestions?


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: asimes on April 01, 2012, 07:06:20 AM
I finally figured out how to view it from a 90 degree rotated angle (now it seems obvious). I just swap the 'y' and 'z' values for the Mandelbulb code as the initialization to 'ny' and 'nz' as well as when adding to them during the while loop. Still not sure about arbitrary rotations, would I need to shoot the rays separately from the 'x', 'y', 'z' triple loop or is there a clever way to include it?

Here's a result (purely ray marching, no orbit trap color):

(http://i.imgur.com/BOQT2.png)


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: ker2x on April 01, 2012, 01:10:33 PM
congratulation  ;D


Title: Re: the simpliest naive bruteforce code for mandelbulb
Post by: David Makin on April 01, 2012, 02:57:39 PM
Softology, mixing the orbit color with the ray marcher looks great, thanks.

I'm beginning to think that my sketch is just not set up for rotation. The part of the sketch that still somewhat alien to me is the "dr" part. However, it seems to only be affected by 'z', maybe if I had it be affected by 'y' it would give me a top down point of view but I don't know about arbitrary rotation. Any suggestions?

For complete implementation of rotation you need to consider a viewpoint firing rays through each pixel of the screen (a flat plane) the centre of which is a fixed distance from the viewpoint and such that the plane is perpendicular to the central ray.
Then to change views you can simply transform each "pixels" coordinate from the position in the flat (screen) plane e.g. (+/-0.5,+/-0.5) or (
+/-1,+/-1) to a coordinate in 3D space based on the location of the viewpoint and the location/orientation of the viewing plane.
For each pixel you then have the viewpoint (vx,vy,vz) and the pixel's coordinate (px,py,pz) so for that pixel you compute (px-vx,py-vy,pz-vz) and then normalise this vector which gives a unit direction vector say (dx,dy,dz) for stepping along the ray.
The start position for the ray-stepping could be the viewpoint but often a near-cutting plane is used and in such a case you simply intersect the ray that starts at (ox,oy,oz) in direction (dx,dy,dz) with this near cutting plane and use the resultant point as the start point for stepping for that pixel.
Of course the above is for perspective projection and the closer the viewing plane (screen) is to the viewpoint then the widerthe field of view (or the smaller the camera with respect to the fractal if you prefer).