Search code examples
c#unity-game-enginefractalsmandelbrot

Mandelbrot displays unprecisely


I am trying to visualize the Mandelbrot set using UnityEngine and C#. What I have right now does not look completely wrong but also not right. The Circular shapes for example are very blurred out. Why is that?

enter image description here

Here is the C sharp code I use:

    public void CalcValues(int iterations)
    {
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                C c = new C(mapWidthDefault(width - i - 1), mapHeightDefault(j));
    
                C z = new C(0, 0);
    
                for (int k = 0; k < iterations; k++)
                {
                    z = z * z + c;
                    if (z.abs > upperbound)
                    {
                        pixels[i + j * width] = Color.white;
                        goto end;
                    }
                }
                pixels[i + j * width] = Color.black;
                // Debug.Log(c + ",   " + z + " " + z.abs);
                end:;
            }
        }
        texture.SetPixels(pixels);
        texture.Apply();
    }
    
    private float mapWidthDefault(float x)
    {
        return map(x, 0, width, -3.516f, 1.516f);
    }
    
    private float mapHeightDefault(float x)
    {
        return map(x, 0, height, -1.5f, 1.5f);
    }
    
    private float map(float x, float a1, float a2, float b1, float b2)
    {
        return (x - a1) * (b2 - b1) / (a2 - a1) + b1;
    }

The values I use:

iterations: 10 upperBound: 10 width: 800 height: 450

The only setting I changed for my Texture2D is that I set filterMode to bilinear to remove blur.

and here is my C class:

public class C
    {
        public readonly double Re;
        public readonly double Im;
        public readonly double abs;

        public C(double real, double imaginary)
        {
            this.Re = real;
            this.Im = imaginary;
            this.abs = Re * Re + Im * Im; // squared abs
        }

        public static C operator +(C c1, C c2)
        {
            return new C(c1.Re + c2.Re, c1.Im + c2.Im);
        }

        public static C operator *(C c1, C c2)
        {
            return new C(c1.Re * c2.Re - c1.Im * c2.Im,
                c1.Re * c2.Im + c1.Im * c2.Re);
        }

        public override bool Equals(object obj)
        {
            if (!(obj is C))
                return false;
            return ((C)obj).Re == Re && ((C)obj).Im == Im;
        }
    }

Solution

  • The iteration limit of 10 will only produce a crude image. At the base level, I suggest you use 100 and much greater at deeper levels of zoom.

    Also the upper bound of 10 wastes processing time, since it is known that the value will eventually escape when it is > 2. Wikipedia states

    In other words, the absolute value of zn must remain at or below 2 for c to be in the Mandelbrot set and if that absolute value exceeds 2, the sequence will escape to infinity.

    As far as filtering the image goes, that's the last thing you should think about, for presentation.