Submitted by , posted on 31 January 2003
Image Description, by
I was playing around with my new ATI 9700 card and the DirectX 9 HLSL, and I came up with this pretty Mandelbrot-based pixel shader.
Here's the fx file for the pixel shader. Just load it into the DirectX 9 Effects browser of the DirectX 9 SDK. (Available from msdn.microsoft.com.) Unfortunately, if you don't have an ATI 9500/9700 card, you may not see the exact same image. The beautiful color stripe pattern around the edge of the Mandelbrot set does not appear if you use the RefRast device. I think that the stripes are an artifact of the way the ATI pixel shader pipeline handels floating point overflow.
I would be very interested in hearing from GeForceFx owners how well this shader works on their card. If you have such a card, you might try increasing the MANDEL_STEPS constant, as I understand that the GeForceFX can do many more steps per pixel shader than the ATI 9700.
---- Begin jhp-Mandelbrot.fx
------- end of jhp-Mandelbrot.fx
// Mandelbrot Shader effect file
// (C) Copyright 2003 by John H. Palevich
string XFile = "teapot.x";
int BCLR = 0xff202080;
float4x3 WorldView : WORLDVIEW;
float4x4 Projection : PROJECTION;
#define MANDEL_STEPS 11
int TEXTURESCALE = 2.0;
float4 Pos : POSITION;
float2 Tex0 : TEXCOORD0;
float3 Pos : POSITION,
float3 Norm : NORMAL)
VS_OUTPUT Out = (VS_OUTPUT)0;
float3 P = mul(float4(Pos, 1), (float4x3)WorldView); // position (view space)
Out.Pos = mul(float4(P, 1), Projection); // position (projected)
Out.Tex0.x = Pos.z; // Compute Tex0 U and V from position.
Out.Tex0.y = Pos.x;
Out.Tex0 *= TEXTURESCALE;
float2 MandelbrotStep(float2 a, float2 t0) : COLOR
float2 a2 = a * a;
result.x = a2.x - a2.y;
result.y = a.x * a.y * 2;
result += t0;
float4 PS20(VS_OUTPUT In) : COLOR
Color.rg = In.Tex0;
Color.b = 0;
Color.a = 1;
for(int i = 0; i < MANDEL_STEPS; i++)
Color.rg = MandelbrotStep(Color.rg, In.Tex0);
// Clamping is required if you want the output to look the
// same on both the Ref-Rast and the ATI 9700.
// But I've commented it out because it ends up
// getting rid of the beautiful stripe fringe effect around
// the main Mandelbrot pattern. (I guess RefRast
// and the ATI card do different things when handleing floating point overflow.
// Maybe it's the difference between 24-bit floating point and 32-bit floating point?
float dist = Color.x * Color.x + Color.y * Color.y;
return dist > 2.0 ? 0.3 : Color; // Replace color fringe pattern with boring grey.
VertexShader = compile vs_1_1 VS();
PixelShader = compile ps_2_0 PS20();