Back to Home

Mandelbrot Animation: 80-bit SSAA 8x8

The implementation of the Mandelbrot fractal animation generator uses 80-bit arithmetic, 8×8 supersampling and OpenMP to create high-quality video. The two-stage pipeline optimizes computations, FFmpeg provides professional encoding.

80-bit Mandelbrot: video with SSAA 8×8 and OpenMP
Advertisement 728x90

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):

Google AdInline article slot
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.

Google AdInline article slot

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.

Google AdInline article slot

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

Advertisement 728x90

Read Next