A little bit of fun with fractals!

**If you don't see anything in the frame above, then either your browser doesn't support WebGL, or your graphics driver is not sufficient for initializing a WebGL context.**

The source code is available on GitHub.

There's nothing special about the way each pixel's color is determined. It's colored based on the number of iterations it takes a point to escape the given distance bound (in this case, *sqrt(10)*) in the Julia set function, just like any other typical fractal viewer.

I decided to have it precompute the color pallet like this:

```
function generateColors() {
colors = new Uint32Array(MAX_ITERATIONS);
var escapeTime, red, green, blue;
for (var i = 0; i < colors.length; i++) {
escapeTime = i/MAX_ITERATIONS;
red = (-Math.cos(escapeTime*Math.PI) + 1)/2*0xff;
green = Math.sin(escapeTime*Math.PI)*0xff;
blue = (Math.cos(escapeTime*Math.PI) + 1)/2*0xff;
colors[i] = (0xff000000 | red | green << 8 | blue << 16);
}
}
```

...and here's what the color functions look like on a graph, where blue starts off strong and dies off, green peaks in the middle, and red ends up strong:

The viewer is made up of a few small components:

- A
**viewport**, which finds the rectangle on the complex plane to render based on given*translation coordinates*, a*zoom multiplier*, and the current*window resolution*. - A
**bitmap**, which holds the most up-to-date*image buffer*to display via WebGL. Sections of it are continuously overwritten by the**renderer**. - A
**renderer**, which calls the Julia set function continuously, limiting each execution time a maximum of*20ms*and keeping track of where it left off in the**bitmap**between each call. It also keeps track of the*offset*(a complex number to add to a point each time it's squared in the Julia set function). - A
**controller**, which sets up the head-up display*buttons*,*text*, and user input*listeners*to modify the*zoom*and*center*of the**viewport**and randomly select new*offsets*for the Julia set function.

Everytime you hit **+** to zoom in, the *zoom* of the **viewport** is multiplied by *1.5*. The **viewport** generates a rectangle every frame by essentially dividing a given starting rectangle's width and height by the *zoom*.

Because of this setup, if you zoom in far enough, you'll crash into a pixelated mess:

This is due to the floating point numbers having limited precision - in the case of JavaScript, floating point numbers are 64-bit. You may also notice that the **viewport**'s *center* snaps while panning when you're zoomed in that far.

The graphics are provided by WebGL via the wonderful IvanK.js. The Julia set itself is, however, ironically software rendered - mainly because IvanK.js isn't intended for use alongside low level access to WebGL.. and I wanted to see how fast I could get it to work in pure JavaScript. c:

No fragment shaders were ~~butchered~~ written in the making of this demo.