Welcome to Fractal Forums

Fractal Math, Chaos Theory & Research => Mandelbulb Implementation => Topic started by: Qythyx on November 23, 2009, 01:42:46 PM




Title: mmm, chocolate
Post by: Qythyx on November 23, 2009, 01:42:46 PM
I've finally got my renderer working so I wanted to share and discuss ideas.

First, you can see all of the following in their full 4x X 4k size at http://mager.smugmug.com/Art/Mandelbulb (http://mager.smugmug.com/Art/Mandelbulb). Here're are few examples:

6,7, and 8 iterations:
(http://mager.smugmug.com/Art/Mandelbulb/full-6-4kx4k/721591136_LAemr-S.jpg) (http://mager.smugmug.com/Art/Mandelbulb/full-7-4kx4k/721591162_mfnKS-S.jpg) (http://mager.smugmug.com/Art/Mandelbulb/full-8-4kx4k/721591179_5Qd9n-S.jpg)


Some analysis of my program shows a lot of time in the function that calculates the {x, y, z} ^ 8. I'm still using a pretty straight forward trig version, because the algebraic versions I've seen don't work for me. One problem is that they all seem to have a division such that the denominator can by zero and therefore cause problems. Does anyone have an algebraic version working? For reference, my function is below (in C#).


Code:
private static void VectorToThe8thTrig2(ref double x, ref double y, ref double z)
{
double x2 = x * x;
double y2 = y * y;
double z2 = z * z;

double r2 = x2 + y2 + z2;
double r_pow = Math.Pow(r2, _Power / 2);
double thetaOrder = Math.Atan2(Math.Sqrt(x2 + y2), z) * _Power;
double phiOrder = Math.Atan2(y, x) * _Power;
double sinThetaOrder = Math.Sin(thetaOrder);

x = r_pow * sinThetaOrder * Math.Cos(phiOrder);
y = r_pow * sinThetaOrder * Math.Sin(phiOrder);
z = r_pow * Math.Cos(thetaOrder);
}


Title: Re: mmm, chocolate
Post by: fractalrebel on November 23, 2009, 05:44:47 PM


Some analysis of my program shows a lot of time in the function that calculates the {x, y, z} ^ 8. I'm still using a pretty straight forward trig version, because the algebraic versions I've seen don't work for me. One problem is that they all seem to have a division such that the denominator can by zero and therefore cause problems.

I add 1e-10 to the radius.


Title: Re: mmm, chocolate
Post by: Qythyx on November 25, 2009, 01:33:17 AM
Fractalrebel, thanks for the tip. Doing that now works with the algebraic version, which is somewhat faster than the trig version.

Here's an angled view of the bulb at 6 iterations. The 4k version is at http://mager.smugmug.com/Art/Mandelbulb (http://mager.smugmug.com/Art/Mandelbulb).

(http://mager.smugmug.com/Art/Mandelbulb/full-angle-6-4kx4k/723040970_2fHb2-S.jpg)


I'm now working on optimizing my ray marching. My basic algorithm now is as follows.
  • Do a one time ray trace from the camera to the center of my bulb and do a binary search to determine the distance to the edge of be bulb. I use this distance to give me a starting point for future traces so I don't need to march along the ray when it's too distant from the bulb. The only problem with this is it is possible my test ray gives a distance too close to the bulb. I'm thinking I'll either do multiple test rays, or just adjust the distance by a constant factor.
  • When I'm doing the normal ray tracing I start at the above calculated distance from the bulb and march along the ray in steps that are about the size of what one pixel would be in my 3d space. When I find a point in the bulb I do a few iterations of binary search to increase the accuracy.

What I want to try is to increase my ray marching step size by taking advantage of the magnitude of the of the mandelbulb formula instead of just looking at the inside/outside binary result. Here's what I'm thinking.
  • Keep track of the magnitude and/or the number of iteration before escape as I march along the ray.
  • As I march, if the magnitude starts increasing again then I do a binary search from the previous checked point to see if I skipped over a hit. My thinking is that as I march into the bulb the magnitude should decrease at each step. So, if it starts increasing I might have missed something.
  • I'd probably just do the binary search until I hit a size something smaller than 1 pixel (maybe 1/4 pixel) and if I don't get a hit by then I skip it.

Has anyone tried anything like this? I'm worried it could miss some hits. I'm also not sure how much of a speed up it'll provide.