TBT – Mandelbrot

One of the last programs I wrote as an undergraduate computer science student was a Mandelbrot fractal renderer using the Escape Time algorithm for my Computer Graphics course.  The key piece is this:

//Escape Time algorithm
int mandelbrot (vec2 uv, float scale) {
	vec2 complexNumber;
	//zoom-to location:
	complexNumber.x = -1.3495-2.5*scale + (uv.x * 3.5*scale);
	complexNumber.y = -0.06489-1.0*scale + (uv.y * 2.0*scale);
	//algorithm starts here:
	vec2 z = vec2(0.0);
	vec2 zsq = vec2(0.0);
	for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
		if (zsq.x + zsq.y < 4.0) {
			z.y = 2.0 * z.x * z.y + complexNumber.y;
			z.x = zsq.x - zsq.y + complexNumber.x;
 
			zsq = z * z;
		}
		else {
			return iteration;
		}
	}
	return MAX_ITERATIONS;
}

In honor of Throwback Thursday, I put together a shader based on that original code, and without any fixes for things like precision issues, although I did sort of indirectly accept a challenge posted by “iq” on Shadertoy to show an aliased fractal and an antialiased fractal side by side to demonstrate the improvement.  The result was actually pretty good, and it zooms in real-time – which is a lot more than I could say for the renderer I wrote in 2003 – but the precision issues really put a damper on zooming in on things to examine them.  Pixels appear to grow as the zoom scaling gets larger as you can see here:

mandelbrot_precision_issue
Click on the image to see a larger version. Mandelbrot precision issues (visible as pixelation)

At reduced zoom levels, the fractal is sharp, even at full-screen resolution, and antialiasing seems to make it look even more appealing.

mandelbrot
Click on the image to see a larger version. As you can see, the aliasing on the left side is pretty rough.

Putting things together – Magnifying Lens (Fresnel) shader

In an effort to start putting concepts together, I’ve combined some parts from two of my initial efforts (the interactive sphere and Perlin noise) into a single demonstration.  I’ve also been interested in understanding how Fresnel reflection and refraction work, and so today I spent my afternoon assembling a fun shader to do all of this.  The subtle challenges inherent in this shader:

  1. Getting the Perlin noise to scroll infinitely to the right
  2. Using a Fresnel reflection and a Fresnel refraction
  3. Doing it all by ray tracing a sphere
magnifyinglens
Click on the image to see the “Magnifying Lens” Fresnel shader

Perlin Noise

Today’s entry is about Perlin noise – I came across Ken Perlin’s reference implementation of improved Perlin noise while looking for information about noise in general.  It was a complete mystery to me until I found The Perlin noise math FAQ, which explained the basics of how the noise algorithm works.

I wanted to put something together for a simple Perlin noise shader, and I made an attempt or two before getting frustrated by GLSL’s mod() function , which did not work exactly the way I expected (integer support?).  I probably could have kept going and hashed something out, but instead I decided to look up an implementation that I had seen referenced on ShaderToy elsewhere:

It worked right out of the box, and there really wasn’t much to it, so I threw in an improvised zoom effect, which I altered slightly to become more like a Ken Burns effect, although I’m really just flipping coordinates for the outputted buffer over time.  Here’s the result:

perlinnoise
Click on the image to see the “Perlin noise with a Ken Burns effect” shader

Perlin Noise – Ken Burns effect

RenderLoupe: the art and science of real-time computer graphics

I decided at some point in the last couple of weeks that I wanted to put together a site that would look at some of the real-time computer graphics gems that I’ve either created or come across in my work. RenderLoupe is the culmination of this desire.

Why “RenderLoupe”?  Well two reasons:

  1. To anyone knowledgeable about computer graphics, there’s an obvious play on words here with “render loop”.
  2. Since we’re going to be looking at things, and perhaps scrutinizing them, the idea of looking at things through a loupe really appealed to me.

To start off with, just to whet your appetite, I have links to a couple of sites that allow you to write GLSL in the browser:

  1. ShaderToy (a lot of times this is a very slow loading site, so be patient!)
  2. GLSL Sandbox Gallery

On ShaderToy, I wrote a couple of simple shaders to get started – if you’re interested in seeing “what is possible” in the browser, there are a lot of great examples.  The first one I wrote is an edge detection shader, which uses matrix convolutions, such as the Sobel kernel, to highlight places in the image where there is a significant change in luminance from one pixel to another.  I decided to include a number of other kernels as options.  The shader source is documented, so here you go:

simpleEdgeDetection
Click on the image to see the “Real-time edge Detection” shader

I also wrote a shader that casts rays at a sphere in real time.  You can drag the mouse and the eye/viewpoint will update accordingly:

simpleSphere
Click to see the “Simple sphere ray casting” shader (trace with no bounce)