Generierung von Mandelbrot-Fraktalanimationen mit 80-Bit-Präzision und SSAA
Das Programm generiert 255 Einzelbilder der Mandelbrot-Menge im BMP-Format bei 1920×1080 Auflösung und kompiliert sie zu einem MP4-Video mit 30 FPS. Die FFmpeg-Integration automatisiert die gesamte Pipeline: von den Fraktalberechnungen bis zum finalen Render. Die FFmpeg-Parameter sind optimiert, um Details zu erhalten: qp=20 gewährleistet hohe Qualität, pix_fmt yuv420p garantiert Kompatibilität und deblock=-6 minimiert Kompressionsartefakte.
Wichtige Befehlsoptionen:
- -stream_loop 3: vier Animationsdurchläufe (Basis + 3 Wiederholungen)
- -framerate 30: Eingabe-Bildrate
- -color_range full: voller Helligkeitsbereich 0-255
- no-psy: deaktiviert psycho-visuelle Verbesserungen für die Reinheit der Fraktalstrukturen
Tastenkürzel und Punktkoordinaten
Das Programm unterstützt die Auswahl aus 8 voreingestellten Bereichen der Menge oder das Laden von Parametern aus einer Mandelbrot.txt-Datei (Taste 9). Koordinaten werden mit 80-Bit-Präzision (long double) gesetzt:
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-Arithmetik und x87-FPU
Die Implementierung verwendet long double, um mit einem Skalierungsbereich von 10^18 zu arbeiten (gegenüber 10^14 für double). Die Hardware-Unterstützung für die x87-FPU gewährleistet maximale Berechnungsgenauigkeit ohne Software-Emulation. Dies ist kritisch für tiefe Zooms in Mini-Fraktale ohne Pixelbildung.
Vorteile der 80-Bit-Präzision:
- +4 Dezimalstellen Genauigkeit
- 10.000 Mal tiefere Skalierung als Standardimplementierungen
- Direkte Nutzung von x87-Registern ohne Zwischenkonvertierungen
Parallelisierung mit OpenMP
OpenMP wird verwendet, um Iterationsberechnungsschleifen zu parallelisieren. Die Direktive #pragma omp parallel for schedule(dynamic) verteilt die Last effektiv auf die Kerne und gewährleistet Skalierbarkeit von 4-Kern-Systemen bis zu Servern mit 128 Threads.
8×8-Super-Sampling (64 Samples pro Pixel)
SSAA wird implementiert, indem bei ultra-hoher Auflösung 15360×8640 (8× das originale 1920×1080) gerendert wird. Jedes finale Pixel aggregiert 64 unabhängige Fraktal-Samples mit separaten RGB-Komponentenberechnungen.
Glättungsalgorithmus:
- Berechnung der Iterationen für jedes Sub-Pixel in 80-Bit-Arithmetik
- Unabhängige Färbung der Sub-Pixel mit Palettenrotation
- Akkumulierung der R/G/B-Intensitäten (Kanaldurchschnitt)
- Herunterskalieren auf die Zielauflösung
Ergebnis: kein chromatisches Rauschen, kinoreife Klarheit der Fraktalstrukturkanten.
Optimierte Einzelbildgenerierung
Die Pipeline ist in zwei Stufen unterteilt, um Berechnungen zu minimieren:
Stufe 1: Iterationskarte
- Erstellen eines uint8_t-Arrays mit 132 MB Größe (15360×8640)
- Einmalige Ausführung der do-while-Iterationsschleife für die gesamte Animation
- Paralleles Füllen mit OpenMP
Stufe 2: Render 255 Einzelbilder
- Lesen der Iterationskarte aus dem Speicher
- Anwenden einer verschobenen Palette für jedes Einzelbild
- Lokale Mittelwertbildung von 8×8-Blöcken (ohne long double)
- Paralleles Schreiben der BMP-Dateien
Sinus-Palette: 127 + 127 cos(2π a / 255) und 127 + 127 sin(2π a / 255).
Implementierungsbeispiel
#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();
}
Wichtigste Erkenntnisse
- 80-Bit-Präzision long double + FPU x87: Zoom bis zu 10^18 ohne Artefakte
- SSAA 8×8: 64 Samples pro Pixel, vollständige Rauscheliminierung
- Zweistufiges Render: 132 MB Iterationskarte + schnelle Farbzusammenstellung
- OpenMP: automatische Multithreading mit dynamischer Planung
- FFmpeg-Integration: qp=20, no-psy, deblock=-6 für professionelle Qualität
— Editorial Team
Noch keine Kommentare.