Colors come out of the speakers

Let’s talk about those trippy ass colors you see on all the zooms on youtube.

Right now we’ve got a pretty simple true false test that tells us if a pixel is not in the set or if, as far as we know, it is. Every extra iteration increases the fidelity of that second category, as you can see in the doodad above. The thing is, we’re throwing away some information here. We’re throwing away how many iterations it took us to figure out that a point was not in the set. This is really interesting information!

Currently, the render function uses the boolean value returned by isMandlebrot to decide whether or not to set the opacity ‘byte’ to either 255, or 0.

We can change isMandlebrot to return a tuple instead, of two things: the original boolean value and the iterations required to divine it.

Now, back in the render function, we can use that information to color the pixel according to it’s iteration score!

set here is a value that I’m first normalizing between 0 and 1, then scaling to be between 0 and 16777215. Then I’m extracting RGB values in kind from it with some bit twiddling. Sorry I’m not explaining that more/better, I’m turning the iteration count into a color value is all!

This is dramatically cooler looking.

Remember those little thingers from before? Look what one of them looks like in color!

Alright! This totally works and is beautiful! But, it’s slow. On the one hand of course it is, this is a lot of computation. But on the other hand… I can do better.

So, I’ve made a little doodad that computes Mandelbrots on the gpu using WebGL. It lives here:

http://mandelbrot.jfo.click

All of the illustrations above that aren’t example canvases were made with this tool. I’ve really enjoyed playing with it! You can even resize the canvas to download high resolution backgrounds as large as you want! Though of course the bigger they go, the slower they’ll run, but just give it a try and see what you can find.

I am not going to explain the code in the webgl widget just yet for a few reasons. First, I’m really happy with how the final product turned out, but the code is a wreck, organizationally! And anyway, most of it is boilerplate to get the webgl connected and up and running, and the parts that aren’t boilerplate aren’t substantially different from the code I’ve shown in vanilla javascript over the course of this post.

I hacked together this widget using:

The author, Greggman, also maintains a library called twgl.js for making the WebGL api less verbose and I am definitely going to use it next time.

Íñigo Quílez, who created shadertoy, also practically has the market cornered on Mandelbrot renders. That link served as both inspiration for this whole thing (wait… we can compute in real time now?) and model while porting my js code over to webgl. I have that shader to thank for that incredible coloring function that I used as the base of mine; I’m still not entirely sure how it works.

A few caveats- this isn’t really designed for mobile. UX wise it’s definitely not, but more importantly mobile platforms don’t seem to have the same caliber of graphics processing as a lap or desktop. This isn’t really a huge surprise; you might be able to get it to render something, but no promises.

Also, unfortunately, current GLSL only natively supports 32 bit floats for use on the gpu, so we run out of precision relatively quickly on the widget. You can barely see where the pixels become blockish at the highest zooms, but don’t be mistaken- this is not the end of the set- the set goes on forever. There are techniques to work around this and achieve a higher precision, but my mandelbrot shed doesn’t need another coat of paint before shipping. I’ll likely try to get around to that sometime, or just put it off until 64 bit floats are native to the platform!