Title: How do I convert a Mandelbrot to a Mandelbulb? Post by: Bottleneck on December 03, 2011, 01:52:42 PM Hi,
First of all I want to thank you for letting me use your forums. Very much appreciated. :D Now my problem is I'm trying to convert a Mandelbrot to a Mandelbulb. The Mandelbrot code comes from one of the Nvidia samples that you get when you install their Cuda SDK. (on a side note: The calculated mandelbrot data is saved in a texture which is rendered using OpenGL) TL;DR: So how do I convert a Mandelbrot to a Mandelbulb? Title: Re: How do I convert a Mandelbot to a Mandelbulb? Post by: eiffie on December 03, 2011, 05:45:01 PM Start by learning the math. Check the mandelbulb wiki. Instead of complex numbers, triplex numbers are used and
Z=Z^2+C becomes:(in glsl) float r=length(Z); //Z is now a 3d vector float zo = asin(Z.z / r) * p; //p is power, usually 8 instead of 2 float zi = atan(Z.y, Z.x) * p; Z=pow(r,p)*vec3(cos(zo)*cos(zi),cos(zo)*sin(zi),sin(zo))+C; //there are variations to this swapping sin/cos But now you have a bigger problem - how to render a 3d object to a 2d screen. Learn about ray-marching with distance estimation. A distance estimation formula tells you how far you can safely move the ray until you need to check again. A mandelbulb DE formula looks like this: float DE(vec3 Z){ vec3 C=Z; float dr = 1.0; //this is a running derivative float r = length(Z); for (int n = 0; n < iterations && r<2.0; n++) {//about 7 iterations will do for starters float zo = asin(Z.z / r) * p; float zi = atan(Z.y, Z.x) * p; float zr = pow(r, p-1.0); dr = dr * zr * p + 1.0; //do you see what is meant by a running derivative here? Z=zr*r*vec3(cos(zo)*cos(zi),cos(zo)*sin(zi),sin(zo))+C; r = length(Z); } return 0.5*r*log(r)/dr; } TL;DR: Check out Boxplorer code for an OpenGL sample. Oh wait a MandelBOT!?! Sorry can't help :) Title: Re: How do I convert a Mandelbot to a Mandelbulb? Post by: huminado on December 03, 2011, 06:51:34 PM Help me understand?
A ray is cast from every 2D camera point away from the camera. At the face of the camera, each 2D point has a ray-march of 0 (I'm making up names), which correlates to a vec3(Z) in 3D space. That Z can be plugged into the 3D formula to determine whether a point in 3D space is inside the boundary of the fractal. Ray-marching could iterate steps away from the camera, but it's too inefficient, so the DE() function returns an estimated step distance for the ray to march forward. In other words, the ray starts at the camera lens and is iterated forward by ray1=DE(ray0), which 3D space point is then plugged into the fractal formula "is this inside the boundary?", if not, ray2=DE(ray1), to iterate it forward until it reaches the boundary. Is this correct? (And if so, aren't binary searches more efficient? [edit] And if you store the adjacent 2D point's DE, can it contribute to this point's DE?) Title: Re: How do I convert a Mandelbot to a Mandelbulb? Post by: eiffie on December 03, 2011, 08:01:18 PM Very good. When the return value dist=DE(ray) is less than the size of a pixel at that distance than you quit and say I hit the fractal. Like this
rayDir is the normalized direction of the ray march ray is the point we are testing, it starts at the camera lens eps is an estimate of the pixel size maxRayLen is the bound and marching steps can vary, about 100 to start for(int i=0;i<marchingSteps && dist>eps && rayLength<maxRayLen;i++){ rayLen+=dist=DE(ray+rayLen*rayDir); } This is actually quite fast! Think about a simple DE like a sphere of radius 1... float DE(Z){return length(Z)-1.0;} If you are aiming right at it you hit in 1 step. If you miss it completely it takes a few more and you reach maxRayLen. The interesting part is near the edges. This will take many steps and may seem inefficient but the number of steps gives you an approximate occlusion of light so you could even just color the fractal with... color=diffuse*(1.0-float(i)/float(marchingSteps)); But thats your next step learning lighting calculations. Yes there are programs that use monte carlo methods etc. If you are using the GPU each pixel is oblivious of its neighbors. The method I've described runs near real time depending on your hardware. Many thanks to the folks here who have contributed to it! Title: Re: How do I convert a Mandelbot to a Mandelbulb? Post by: huminado on December 03, 2011, 10:01:13 PM Very helpful! I've been wondering how to optimize hybrids. Now it's all much clearer. And explains why sometimes ghosting occurs when a surface occludes another surface. [All I can think of for optimizing hybrids (but it's not practical) is FPGA-based computing, where the processor itself is optimized according to the code profile. Not really a PC-based solution...] |