| 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

    // Mandelbrot Shader effect file
    // (C) Copyright 2003 by John H. Palevich

    string XFile = "teapot.x";
    int    BCLR  = 0xff202080;

    // transformations

    float4x3 WorldView  : WORLDVIEW;
    float4x4 Projection : PROJECTION;

    #define MANDEL_STEPS 11
    int TEXTURESCALE = 2.0;

    struct VS_OUTPUT
    {
        float4 Pos  : POSITION;
        float2 Tex0 : TEXCOORD0;
    };

    VS_OUTPUT VS(
        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;

        return Out;
    }

    float2 MandelbrotStep(float2 a, float2 t0) : COLOR
    {
        float2 result;
        float2 a2 = a * a;
        result.x = a2.x - a2.y;
        result.y = a.x * a.y * 2;
        result += t0;
        return result;
    }

    float4 PS20(VS_OUTPUT In) : COLOR
    {
        float4 Color;
        Color.rg = In.Tex0;
        Color.b = 0;
        Color.a = 1;

        int i;
        for(int i = 0; i < MANDEL_STEPS; i++)
        {
            Color.rg = MandelbrotStep(Color.rg, In.Tex0);
        }
    #ifdef CLAMP_COLORS
        // 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.
    #else
        return Color;
    #endif
    }

    technique TMandelbrot_PS_2_0
    {
        pass P0
        {
            VertexShader = compile vs_1_1 VS();
            PixelShader  = compile ps_2_0 PS20();
        }
    }

------- end of jhp-Mandelbrot.fx

[prev] | Image of the Day Gallery www.flipcode.com | [next]

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.