Generating Mandelbrot Fractal Animation with 80-Bit Precision and SSAA
The utility generates 255 frames of the Mandelbrot set in BMP format at 1920×1080 resolution and compiles them into an MP4 video at 30 FPS. FFmpeg integration automates the entire pipeline: from fractal calculations to the final render. FFmpeg parameters are optimized to preserve detail: qp=20 ensures high quality, pix_fmt yuv420p guarantees compatibility, and deblock=-6 minimizes compression artifacts.
Key command options:
- -stream_loop 3: four animation passes (base + 3 repeats)
- -framerate 30: input frame rate
- -color_range full: full brightness range 0-255
- no-psy: disables psycho-visual enhancements for purity of fractal structures
Hotkeys and Point Coordinates
The program supports selecting from 8 preset regions of the set or loading parameters from a Mandelbrot.txt file (key 9). Coordinates are set with 80-bit precision (long double):
case 1: absc = -0.5503432753421602L; ordi = -0.6259312704294012L; size_val = 0.0000000000004L; break;
case 2: absc = -0.691488093510181825L; ordi = -0.465680729473216972L; size_val = 0.000000000000003L; break;
case 3: absc = -0.550345905862346513L; ordi = 0.625931416301985337L; size_val = 0.000000000000005L; break;
case 4: absc = -1.78577278039667471L; ordi = -0.00000075696313293L; size_val = 0.000000000000004L; break;
case 5: absc = -1.785772754399825165L; ordi = -0.000000756806080773L; size_val = 0.0000000000000014L; break;
case 6: absc = -1.40353608594492038L; ordi = -0.02929181552009826L; size_val = 0.000000000000095L; break;
case 7: absc = -1.7485462508265219L; ordi = 0.000002213770706L; size_val = 0.00000000000029L; break;
case 8: absc = -1.94053809966024986L; ordi = -0.00000120260253359L; size_val = 0.00000000000003L; break;
80-Bit Arithmetic and x87 FPU
The implementation uses long double to work with a scaling range of 10^18 (versus 10^14 for double). Hardware support for the x87 FPU ensures maximum calculation accuracy without software emulation. This is critical for deep zooms into mini-fractals without pixelation.
Advantages of 80-bit precision:
- +4 decimal digits of precision
- Scaling 10,000 times deeper than standard implementations
- Direct use of x87 registers without intermediate conversions
Parallelization with OpenMP
OpenMP is used to parallelize iteration calculation loops. The #pragma omp parallel for schedule(dynamic) directive effectively distributes the load across cores, ensuring scalability from 4-core systems to servers with 128 threads.
8×8 Super-Sampling (64 Samples per Pixel)
SSAA is implemented by rendering at ultra-high resolution 15360×8640 (8× the original 1920×1080). Each final pixel aggregates 64 independent fractal samples with separate RGB component calculations.
Smoothing algorithm:
- Calculate iterations for each sub-pixel in 80-bit arithmetic
- Independent coloring of sub-pixels with palette rotation
- Accumulate R/G/B intensities (channel averaging)
- Downsample to target resolution
Result: no chromatic noise, cinematic clarity of fractal structure edges.
Optimized Frame Generation
The pipeline is divided into two stages to minimize calculations:
Stage 1: Iteration Map
- Create a uint8_t array sized 132 MB (15360×8640)
- Execute the do-while iteration loop once for the entire animation
- Parallel filling with OpenMP
Stage 2: Render 255 Frames
- Read iteration map from memory
- Apply shifted palette for each frame
- Local averaging of 8×8 blocks (without long double)
- Parallel writing of BMP files
Sinusoidal palette: 127 + 127 cos(2π a / 255) and 127 + 127 sin(2π a / 255).
Implementation Example
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdint>
#include <string>
#include <atomic>
#include <omp.h>
#include <cstdio>
using namespace std;
const double PI = 3.14159265358979323846;
#pragma pack(push, 1)
struct BMPHeader {
uint16_t type{0x4D42};
uint32_t size{0};
uint16_t reserved1{0};
uint16_t reserved2{0};
uint32_t offBits{54};
uint32_t structSize{40};
int32_t width{0};
int32_t height{0};
uint16_t planes{1};
uint16_t bitCount{24};
uint32_t compression{0};
uint32_t sizeImage{0};
int32_t xpelsPerMeter{2834};
int32_t ypelsPerMeter{2834};
uint32_t clrUsed{0};
uint32_t clrImportant{0};
};
#pragma pack(pop)
void save_bmp(const string& filename, const vector<uint8_t>& data, int w, int h) {
int rowSize = (w * 3 + 3) & ~3;
BMPHeader header;
header.width = w;
header.height = h;
header.sizeImage = rowSize * h;
header.size = header.sizeImage + 54;
ofstream f(filename, ios::binary);
f.write(reinterpret_cast<char*>(&header), 54);
f.write(reinterpret_cast<const char*>(data.data()), data.size());
f.close();
}
Key Takeaways
- 80-bit precision long double + FPU x87: zoom up to 10^18 without artifacts
- SSAA 8×8: 64 samples per pixel, complete noise elimination
- Two-stage render: 132 MB iteration map + fast color assembly
- OpenMP: automatic multi-threading with dynamic scheduling
- FFmpeg integration: qp=20, no-psy, deblock=-6 for professional quality
— Editorial Team
No comments yet.