Skip to content

Instantly share code, notes, and snippets.

@GuyInGrey
Created March 17, 2021 14:15
Show Gist options
  • Save GuyInGrey/587cf95fc2d8a4de59c65f57a3f17ccd to your computer and use it in GitHub Desktop.
Save GuyInGrey/587cf95fc2d8a4de59c65f57a3f17ccd to your computer and use it in GitHub Desktop.
[Command("mandelbrot")]
public async Task Mandelbrot()
{
var maxToRun = 40;
var frames = 3600;
var path = @"C:\RenderingTemp\";
var colors = Enumerable.Range(0, maxToRun + 1).Select(i => Paint.Lerp(Paint.White, Paint.Black, i / (float)maxToRun)).ToArray();
if (Directory.Exists(path)) { try { Directory.Delete(path, true); } catch { } }
Directory.CreateDirectory(path);
float Mandelbrot(float x, float y, float max, float pow)
{
var c = new Complex(x, y);
var z = Complex.Zero;
var i = 0;
while (Complex.Abs(z) <= 2 && i < max) { z = Complex.Pow(z, pow) + c; i++; }
if (i == max) { return max; }
return (float)(i + 1 - Math.Log(Math.Log(Complex.Abs(z))) / Math.Log(2));
}
Sprite Render(int j)
{
var s = new Sprite(4000, 4000);
var pixels = new byte[s.Width * s.Height * 4];
for (var q = 0; q < s.Width * s.Height; q++)
{
(var x, var y) = (q % s.Width, q / s.Width);
var x2 = PMath.Map(x, 0, s.Width, -2.25f, 0.75f);
var y2 = PMath.Map(y, 0, s.Height, -1.5f, 1.5f);
var i = Mandelbrot(x2, y2, maxToRun, PMath.Map(j / (float)frames, 0, 1, 0, 4));
i = i == 0 ? 0.000001f : i;
var c = float.IsNaN(i) ? Paint.Red : Paint.LerpMultiple(colors, i / (float)maxToRun);
var pos = q * 4;
pixels[pos] = (byte)c.B;
pixels[pos + 1] = (byte)c.G;
pixels[pos + 2] = (byte)c.R;
pixels[pos + 3] = (byte)255;
}
s.Art.SetPixels(pixels);
return s;
}
await ReplyAsync($"Rendering...");
var time = DateTime.Now;
var totalFinished = 0;
Parallel.For(0, frames, new ParallelOptions() { MaxDegreeOfParallelism = 3 }, i =>
{
var s = Render(i);
s.Save($@"{path}{i:000000}.png");
s.Dispose();
if (time.Add(new TimeSpan(0, 1, 0)) < DateTime.Now)
{
time = DateTime.Now;
ReplyAsync($"🦥 `{((float)totalFinished / (float)frames) * 100f}%`, `{totalFinished} / {frames}`");
}
totalFinished++;
});
await ReplyAsync("Render complete, compiling into video...");
await Extensions.FFMPEG(" -framerate 60 -i %06d.png -c:v libx264 -r 60 output.mp4", path);
await ReplyAsync($"{Context.User.Mention}, uploading...");
await Context.Channel.SendFileAsync($"{path}output.mp4");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment