Saturday, October 10, 2009

I recently became interested in fractals, and was working on my own little fractal library in Clojure. Base Clojure really isn't bad for generating fractals, due to the very strong concurrency primitives and the ability to work with pretty much any java structure you want. I managed to get my version (in pure Clojure), up to about 98% CPU usage on 2 processors over the course of making a fractal. Which I thought was pretty good.

But Penumbra is f*cking amazing.

Penumbra Is a really, really neat library by Zach Tellman that allows you to do GPU processing using Clojure. Not only can you do graphics stuff (drawing on the screen), but you can also do general purpose computations in parallel, using a sort of map-reduce framework (GPGPU, I think it is called). Anyway, the library itself is a seriously slick example of macros and beautiful lisp-style hackery. Aside from that, installation was also a breeze.

If you look at Zach's blog, you can see that there is a Mandelbrot explorer program that he wrote. It is really impressive, and it comes in the /examples directory when you download Penumbra.

I only really learn by tearing things apart and putting them back together. A list of things to tinker with:

Firstly, you'll notice that there is a sort of banding effect in the generated fractals. It is not easy to notice in the video, but using the example code at full screen, you can tell. Lets see what we can do about this.

Secondly, it is really only using two colors, blue and white. A lot of the time you have fractals that do like multiple colors or at least are more interesting colors.

Thirdly, try to make it so that you can both zoom in and out, and move around, as seperate functionalities.

The default coloring function used is pretty basic. Escape time algorithm with color-mixing.
We can change it to a normalized iteration count and instead:





So you get pictures that look more like this:


From FRACTALS

Ok, so next would be adding more color, which can be fairly finicky.
The obvious thing is to do different combinations with the normalized count algorithm.
That's pretty easy, so we won't do that.
The next most obvious thing is to use the HSV color wheel and convert to RGB.
That's harder, so we'll do that. The code is this:



So in this code, h is on a scale of 360.0 to 0.0 in which different degrees correspond to different colors.
Here's a couple pictures using this sort of scale:
From FRACTALS

From FRACTALS

From FRACTALS


I think that potentially the most confusing thing about the DSL that makes these 'kernels' is that it doesn't seem that let works in exactly the same way as it would in a lisp like Clojure. for example I might nest a let inside a ternary statement, but I had difficulty compiling when I tried to do that. (Perhaps I was simply doing it wrong). Another minor confusion that you have to get around is that the numbers must be typed, and you can't really mix types. So the difference between 1.0 and 1 is important.

The last little hack I did was to change around the UI... Pretty much I changed the mouse click function so it just changes location, and made it so the Z and X keys are zoom in and out respectively.



You'll notice that key-presses are relayed as keywords rather than strings or characters. Nothing terribly complicated there, but the interface seems very polished and thought out to me.

Anyway, I hope this helps anyone who wishes to poke around with Penumbra.
Check it out here