Shawn Hargreaves Blog
My friend George Foot suggested this improved version of the Mandelbrot shader I posted yesterday:
float4 PixelShader(float2 texCoord : TEXCOORD0) : COLOR0
float2 c = (texCoord - 0.5) * Zoom * float2(1, Aspect) - Pan;
float2 v = 0;
float m = 0;
const float r = 5;
for (int n = 0; n < Iterations; n++)
v = float2(v.x * v.x - v.y * v.y, v.x * v.y * 2) + c;
if (dot(v, v) < (r*r - 1))
v = clamp(v, -r, r);
if (m == Iterations)
return float4(sin(m/4), sin(m/5), sin(m/7), 1) / 4 + 0.75;
This renders fractals in glorious technicolor:
A similar technique can also be used to render Julia sets, which are closely related to the Mandelbrot. To do this, the beginning of the pixel shader changes to:
float4 PixelShader(float2 texCoord : TEXCOORD0, float4 color : COLOR0) : COLOR0
float2 c = color;
float2 v = (texCoord - 0.5) * Zoom * float2(1, Aspect) - Pan;
float m = 0;
// the rest is identical to the above Mandelbrot shader
Julia sets are defined by a seed value, so we need a variable to store this in the C# code:
Vector2 julia = new Vector2(0.5f);
In the Update method, add a line using the right stick to control the seed position:
julia += new Vector2(pad.ThumbSticks.Right.X, -pad.ThumbSticks.Right.Y) * 0.005f;
And in the Draw method, change the SpriteBatch call to pass the seed into the pixel shader, via the sprite color parameter:
spriteBatch.Draw(dummyTexture, Vector2.Zero, new Color(new Vector3(julia, 0)));
Julia sets are if anything even more fascinating than the Mandelbrot. Different seed values can produce an incredible variety of patterns:
The Mandelbrot set is the catalog of Julia sets. If you take a point near the boundary of the Mandelbrot set, near spirals, the Julia set corresponding to that Mandelbrot point will also contain spirals. Points from a spikey area of M will produce spikey J's. J's from points outside the M boundary will be disconnected; J's from inside the M boundary will be connected or globular.
And to think, Mr Mandelbrot was sure (at first) that the spot of black near the origin on his printouts was was caused by arithmetic roundoff error!
Poor Mr Mandelbrot didn't have a pixel shader to run this stuff on :-)
Crazy to think that what for him was a batch process where a supercomputer had to be left crunching overnight, and you'd get the results as a printout the next morning, I can now do the same thing in totally smooth realtime on a $400 piece of consumer electronics!
Looking back In the beginning there are darkness..., damn stop , too far back Looking back to before...
First off great work, I'm impressed, was going to try to draw a mandelbrot for my first XNA program but mine wouldn't have been anywhere near has good.
Any reason why after a certain amount of zoom, the image gets pixelated and unmovable? can't fractals zoom indefinitly? I changed the fx file so that iterations was a paramter instead of a constant, and that helped, but still I eventually get lots of blocks.
Anyway - great work.
I think it's running up against the limits of 32 bit floating point precision. Fractals can only zoom forever if you have an infinitely precise way of doing your calculations...
I tweaked the code a little to use doubles instead of floats inside the pixel shader, which allows for a little more zooming without pixellation. It still pixellates before I'd expect it to though. I also added the ability to change the number iterations with a couple of buttons which gives a great effect. The max useful iterations is about 254. I can share the code if it's of any use.
Ah, I love Mandelbrot fractals. They are thing that first got me interested in programming