I'm trying to code the Mandelbrot set as a fun project. I did it on my own, so it probably isn't optimized very well. I have a few questions about how to make my code better and how to add certain things to it. I used the library p5js, but that probably doesn't matter. (My code is at the bottom.)
First of all, when I render the set, the edges are very sharp. For example: See how the edges are sharp, because it operates pixel by pixel. However, I see in, for example, the Wikipedia page that it is possible to blend pixels and give more detail to the picture. How might I go about doing this? I've thought about calculating four values for each pixel, and blending them, but I feel like there should be another way.
Secondly, rendering the set takes much longer than it can if I want to animate it. I have to iterate more and more the more I zoom, so each frame would end up taking entire minutes to render. However, then I see videos like this https://www.youtube.com/watch?v=LhOSM6uCWxk or this https://www.youtube.com/watch?v=b005iHf8Z3g and I'd like to know how they are able to render these in less than a century. Is there an optimization method that I'm missing out on?
Another thing about the videos is how they are colored. For example, the first video I showed seemed like the colors were moving around everywhere, instead of staying in a constant spot, like the second video. What is the coloring method?
I've tried making the iterations low, but then I lose quality. I've tried an array of colors, but then it looks flat, like the second video. I want to know what's going on that I'm missing. I've looked at other solutions and seen that some people are rendering one pixel at a time, and that's what is making it slow. I do rows at a time for speed. All in all, what should I change to animate a set that looks pretty cool?
Finally, is there anything else that I should know to make my Mandelbrot set look amazing? Is there a completely different method for rendering that I should know? How is the first video made to look 3D? All of these clarifications would be nice to know.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/addons/p5.sound.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.3.0/math.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
<script src="sketch.js"></script>
</body>
</html>
//noprotect
var y = 0;
var ratio;
var xstart = -2;
var xend = 2;
var ystart = -2;
var yend = 2;
var maxiter = 100;
var _xstart;
var _xend;
const colors = [
"rgb(255, 0, 255)",
"rgb(255, 0, 127)",
"rgb(255, 0, 0)",
"rgb(255, 127, 0)",
"rgb(255, 255, 0)",
"rgb(127, 255, 0)",
"rgb(0, 255, 0)",
"rgb(0, 255, 127)",
"rgb(0, 255, 255)",
"rgb(0, 127, 255)",
"rgb(0, 0, 255)",
"rgb(127, 0, 255)"
];
function setup() {
noStroke();
createCanvas(window.innerWidth, window.innerHeight);
ratio = width/height;
background(0);
_xstart = xstart * (width/height);
_xend = xend * (width/height);
_xstart = (xstart + xend)/2 + xstart*(width/height);
_xend = (xstart+xend)/2 + xend*(width/height);
}
function mandelbrot(rconst, iconst) {
var iter = math.complex(0, 0);
var current = 0;
for(var i = 0; i < maxiter; i ++) {
iter = iter.pow(2);
iter = iter.add(rconst, iconst);
current ++;
if(sqrt(pow(iter.re, 2)+pow(iter.im, 2)) > 2) {
break;
}
}
if(current === maxiter) {
return(0);
} else {
//color array
return(colors[(current) % colors.length]);
//purple
var temp = floor(map(current, 0, maxiter/3, 0, 255));
if(temp > 255) {
temp = 255;
}
// return('rgb(' + temp + ', 0, ' + temp + ')')
//black and white
// return(map(current, 0, 30, 0, 255))
return('rgb(0, 0, ' + temp + ')')
}
}
function draw() {
if(y < height+1) {
for(var x = 0; x < width+1; x ++) {
fill(mandelbrot(map(x, 0, width, _xstart, _xend), map(y, 0, height, ystart, yend)))
rect(x, y, 1, 1);
}
y++;
}
fill(0);
rect(0, 0, 300, 15);
fill(255);
text("x: " + map(mouseX, 0, width, _xstart, _xend) + ", y: " + map(mouseY, 0, height, ystart, yend), 0, 10);
}