Code/FractalMandelbrotGenerator.cs
namespace FractalGen;
[Icon( "donut_small" )]
[Title( "Fractal - Mandelbrot" )]
[ClassName( "mandelbrotgenerator" )]
public class FractalMandelbrotGenerator : Sandbox.Resources.TextureGenerator
{
public int MaxSize { get; set; } = 1024;
[KeyProperty]
public Color Color { get; set; } = Color.Orange;
public Color BackgroundColor { get; set; } = Color.Black;
[KeyProperty]
public int MaxIterations { get; set; } = 50;
public float Zoom { get; set; } = 1;
public Vector2 Offset { get; set; }
public bool InvertColor { get; set; }
[Hide, JsonIgnore]
public override bool CacheToDisk => true;
protected override ValueTask<Texture> CreateTexture( Options options, CancellationToken ct )
{
var bitmap = new Bitmap( MaxSize, MaxSize );
bitmap.Clear( BackgroundColor );
Sandbox.Utility.Parallel.For( 0, bitmap.Height, y =>
{
for ( int x = 0; x < bitmap.Width; x++ )
{
float a = ((float)x).Remap( 0, bitmap.Width, -2 / Zoom + Offset.x, 2 / Zoom + Offset.x );
float b = ((float)y).Remap( 0, bitmap.Height, -2 / Zoom + Offset.y, 2 / Zoom + Offset.y );
int n = GetMandelbrotIterations( a, b );
float brightness = ((float)n).Remap( 0, MaxIterations, 0, 1 );
Color pixelColor = Color.Lerp( BackgroundColor, Color, brightness );
lock ( bitmap )
{
bitmap.SetPixel( x, y, pixelColor );
}
}
} );
if ( InvertColor )
bitmap.InvertColor();
return ValueTask.FromResult( bitmap.ToTexture() );
}
private int GetMandelbrotIterations( float a, float b )
{
float ca = a;
float cb = b;
int n = 0;
while ( n < MaxIterations )
{
float aa = a * a - b * b;
float bb = 2 * a * b;
a = aa + ca;
b = bb + cb;
if ( a * a + b * b > 16 )
break;
n++;
}
return n;
}
}