May 13

Ray Traced Quaternion Julia Sets in WebGL

  • webgl
  • javascript

I was supposed to work on a side project with my wife this weekend. Much to her chagrin, I stumbled on an article about 4k demos which had some great 3d visualizations of fractals, and a new weekend project immediately pushed its way onto my spare-time stack. I’ve been looking for an excuse to try out WebGL with something more complex then a spinning cube example… and there went my weekend.

Initial Steps

Finding a good fractal rendering tutorial turned out to be surprisingly difficult. The Wikipedia article on fractals suffers from a surfeit of information - make it through the first section and you’ve probably jumped out to a dozen other articles, found your clocks have advanced an hour without you noticing, and totally forgotten what it is you were doing. Fortunately, there are simple tutorials out there to get you started rendering the basic 2D Mandelbrot set.

Getting up and running with WebGL is downright silly: grab a boilerplate, and you’re off. No libraries to link to, no plugins to install, and you can iterate by refreshing the page. Combine that with the usual browser developer tools and an extremely nice WebGL Inspector, and it turns out even the debugging environment is as easy as you can get.

But 2D Mandelbrot sets are boring, and while 3D Mandelbulbs are awesome - 3D renderings of 4D Julia sets seem to have a broader range of example code in the wild.

Adding some D-s

There are some great examples out there of rendering Quaternion Julia Sets, but the seminal example seems to be Keenan Crane’s GLSL implementation, which even includes a thoroughly annotated HTML version of the shader code.

Porting Crane’s GLSL code to WebGL’s OpenGL ES 2.0 based shader language turned out to be pretty simple, only requiring a handful of modifications:

  • WebGL uses vecN instead of floatN (where N = [ 2, 3, 4 ])
  • Loop conditions (i < N) cannot use variables. Original behavior is easily emulated using breaks (though likely with some - possibly significant - performance impact).
  • WebGL doesn’t like performing automatic conversions from int to float, so even constants need to include the decimals. E.g.: 4.0 * someFloat

That’s all: porting GLSL programs to WebGL is a breeze.

Fewer jaggies, please

WebGL doesn’t stand up as well when it comes to antialiasing options though. Adding { antialias: true } to the initialization call didn’t seem to do anything (at least in Chrome 18 on OS X). So I opted for the lazy approach: render to a double-sized texture and let a linear texture minification filter have a pass at it by rendering it non-double-sized. Sure enough, render to texture works surprisingly well in WebGL.


WebGL and Javascript form an extremely competent team for rapid graphics prototyping. Refreshing a browser turns out to be a fast method of iteration. Compared to recompiling an executable and running it - not to mention uploading to a device or running in an emulator - this can be a major improvement. With projects like WebGL playground, and no shortage of examples on sites like WebGL Experiments, playing around with graphics technology has never been easier.

You can view the WebGL page here - with the code just a View Source click away.

Now to make the source code 90% smaller while making the output look ten times more interesting…

blog comments powered by Disqus