C++ Escape Time Fractal Program - Improvements
I took a week or so break from coding (Guilty Gear Strive is addicting!) but a couple of days ago I got back into working on the fractal program and I got reimmersed in the project. In around 8 to 10 hours of work I made the following improvements:
Transformation of the output values of the fractal function
Improvements include outputting relative to the number of iterations so that when you increase iterations, existing values stay the same. I also added a logarithmic function on the output so that the rate of color change is generally the same when you zoom in, and some magic, derived-by-educated-guesswork math to transform the 0-to-1 value added to the iteration count (length limit divided by absolute value of the complex number after the function diverges) so that there is a smooth gradient between iterations (I don't know whether to be proud or embarrassed by how I figured that math out but it works fantastically so I'm leaning towards proud; I tested it in multiple scenarios and it seems to work perfectly regardless of what lengthLimit is set to).
With just the iterations output (just outputting "i" without adding ratio, how most escape time fractals work):
Without the "magic math" (ratio is just lengthLimit / value.AbsoluteValue()), better than above but still not quite smooth:
With the magic math: a smooth gradient in between iterations (a rare feature for escape time fractal renderers!)
The other change is a simple logarithmic transformation so that the colors don't explode in complexity as you zoom deep into the fractal and the rate of change in iterations increases, as well as making the zoomed out fractal fairly colorful looking as shown above.
deep zoom without logarithmic transformation:
deep zoom with logarithmic transformation:
Dear ImGui powered UI
With this UI, you can now change several features at run time! You can switch between an animated Julia set or the Mandelbrot set, run or pause the animation of the Julia set, increase or decrease the number of iterations, change the length limit (although it's best to just keep that value as is) or change the period to decrease or increase the frequency of the color ramp:
Convergence detection optimization
Previously, pixels that were drawn black were running the full iterations and causing a lot of slowdown at higher iteration count. I added an optimization that checks the amount of change each iteration and if it's below a certain amount (the "Minimum Deviation") it exits the function early. For most values that are plotted as black this goes towards 0 very fast, so you can set the minimum deviation to a very low number and it will still exit the function very quickly and save a lot of render time. For extra control I added this value to the UI, but even with the default value of 0.000000000000001, for most pixels mapped to black it converges to below this value very quickly and saves a lot of time.
Upsample/Supersample
You can resize the window to smaller to get better performance, but you can also set the "Upsample" value to something between 0 and 1; this will decrease the rendered resolution and increase performance / responsiveness. This is good for zooming into parts of the fractal that reach high iteration counts which slows down the rendering.
If you want a higher quality render, you can set the value to 2 (4 samples per pixel) or 4 (16 samples per pixel). This will functionally add some antialiasing and higher quality to your render at the cost of performance.
Upsample value of 1:
Upsample value of 4:
Loading bar
This was trivial to add because I was already calculating the completion of the fractal threads in order to do the smooth zooming, but now that completion is shown in the UI, so you can track how much time is left before your fractal is done rendering. If it's taking too long, you can change some values and click "Update" and it will stop the current drawing thread and start over with the new settings, so if it's taking too long you don't have to wait.
Link to project:
Comments