*This is all somewhat old but maybe the information will be useful to someone. After all, fractals are still made the same (though much quicker than on a P133...)*

I've been into fractals, and rendering them in three dimensions.

I've been working on my software, and managed to make it run in a batch mode, and utilize offscreen drawing and output to a file. So, now I can easily make animations and do large renderings on remote machines.

All of these are images of the mandelbrot set. They were rendered via the Mesa library, an opengl-ish free graphics library thats available for most flavors of UNIX, including Linux.

These are some early shots...I have a lot of work I still want to do, but I wanted to put something on the web now. The images link to 800x600 jpgs (60 - 80k).A little more info on fractals at the bottom....

These two are the same, with a different number of maximum iterations...

These two are each at 1000 iterations, but with different color schemes...

The mandelbrot set is one type of fractal. It is generated by starting with a grid of points, and applying a function to each point. That function returns a value which can be used as the color, height, etc. for that point in the grid.

Here is some sample code in C. In this example
rloc and iloc are numbers on the real and imaginary plane (graphed
as x and y respectively) and represent where we are starting
from. *rinc* and *iinc* represent the distance between each pixel
we are graphing. So if we are graphing a 200x200 pixel picture,
ranging from (-2, 2) to (2, -2), we would have an *rinc* and *iinc* of
(2 - (-2))/200 or 0.02. *r* and *i* are integers representing
indexes into the 2d array representing the fractal we are creating.

for(r = 0; r < RWIDTH; r++) { /* iterate through the x (real number) plane */ iloc = istart; for(i = 0; i < IWIDTH; i++) { /*iterate through the y (imaginary) plane */ real = 0.0; imag = 0.0; go = 1; for(iters = 0; iters < max_iters && go; iters++) { /* repeat this on the pixel up to max_iters time */ newreal = real * real - imag * imag + rloc; newimag = (real + real) * imag + iloc; real = newreal; imag = newimag; if(real * real + imag * imag > 4) go = 0; } grid[r][i] = color; ilock += iinc; } rloc += rinc; } /* etc */

The inner for loop repeats, starting with real and imag at 0, using the current location as the offset. As it proceeds, the real and imag keep taking on new values. Eventually their values may start towards infinity; once the sum of there squares is 4, this will be the case (don't ask me for the proof. At this point, you record the number of iteration it took before the values of real plus imag squared were greater than 4.

It is also possible that we have gone for a certain number of iterations and real and imag haven't started toward infinity. In that case, record the value of max_iters for them. It is possible that they might have diverged later, had we gone for more iterations, but the more iterations you try, the longer the algorythm takes.

With more iteration, you find higher definition around the edges.

An even easier way to look at it:

What you see in a fractal is a visual representation of a numerical endurance test. Each point in the picture is run through an algorythm until either it gives up, or the algorythm gives up. The area in the center (or the highest area, in a 3D representation) are the points that "made it through" the algorythm. Other points are colored/shaded according to how close they came.

The points on the outside are real lusers.

One of the really cool things about fractals is that they filled within repeating patterns. You can see this clearly in the first picture. All of the round things growing off the main body are similiar in shape. You can magnify these repeatedly and still see the original shape. Its difficult to see this in the close up; take my word for it.