🇬🇧 ENGLISH VERSION: README in English
Модульный C++ проект для генерации фракталов, работы с математическими примитивами и рендеринга изображений в BMP.
Фокус на чистой архитектуре, использовании паттернов, обобщённом дизайне (concepts, templates), численных алгоритмах и расширяемости.
Проект демонстрирует:
- современный C++ (C++20/23),
- использование принципов ООП,
- некоторые паттерны проектирования (билдер, фабричный метод, адаптер, пр.)
- использование концептов,
- математику (комплексные числа, кватернионы, фракталы),
- работу с бинарными форматами изображений,
- модульную архитектуру и тесты.
- Примеры рендеров
- Пример использования функционала
- Сборка
- Структура репозитория
- Основные возможности
- Используемые технологии
- Тестирование
- Архитектурные особенности
- Ограничения
- Возможные направления развития
| Mandelbrot | Julia |
|---|---|
![]() |
![]() |
Создание рендерера происходит через паттерна Fluent Builder. Для раскраски фрактала используется конкретная структура BgrColorizer, которая реализует концепт специального вида. Для рендерера задаются нужные свойства (свойства viewport-а, нужные функции и пр.) и билдится.
Пример ниже иллюстрирует рисование фрактала Мандельброта.
auto renderer =
FractalRendererBuilder<BgrColorizer>
::get_builder()
.set_viewport_width(3)
.set_viewport_center(-0.75)
.set_iteration_func( [](auto& z, auto& c) { return z * z + c; } )
.set_initial_func( [](auto&) { return Complex::Zero(); } )
.set_param_func( [](auto& pixel) { return pixel; } )
.build();
Bmp image = Bmp::empty(2000, 2000);
renderer.render(image);
io::save(image, "mandelbrot_set.bmp");git clone --recurse-submodules git@github.com:vazgensoghoyan/fractal-renderer.git
cd fractal-renderer
mkdir build && cd build # Создаем папку для сборки и переходим в нее
cmake .. # Генерируем сборку через CMake
cmake --build . # сборка всех целей (библиотека + приложение + тесты + примеры)
ctest # (Опционально) Запуск тестов через CTestПосле полной сборки имеем следующие исполняемые файлы:
./iheay_app- usage_examples/
./draw_julia_set./draw_mandelbrot_set./render_animation_mandelbrot
- tests/
- bmp/
./test_bmp
- math/
./test_vec3./test_complex./test_quaternion
- bmp/
fractal-renderer/
│
├── external/ # git submodules (third-party зависимости)
│ ├── googletest/
│ └── raylib/
│
├── include/
│ ├── adapters/
│ ├── bmp/ # структуры формата BMP и IO-функционал
│ ├── fractal/ # алгоритмы рендера фракталов
│ ├── math/ # Vec3, Complex, Quaternion, Ray
│ ├── rasterizer/ # концепт PixeledImage и алгоритмы растеризации к нему
│ ├── ray_tracing/ # движок рей трейсинга (пока почти пуст)
│ └── utils/ # пока тут лишь Logger
│
├── src/ # реализации
│ ├── ...
│ └── main.cpp
│
├── tests/
│ ├── bmp/ # тесты для модуля BMP
│ ├── math/ # тесты для модуля математики
│ └── CMakeLists.txt
│
├── usage_examples/ # небольшие примеры использования функционала
│ ├── CMakeLists.txt
│ ├── draw_julia_set.cpp
│ ├── draw_mandelbrot_set.cpp
│ └── render_animation_mandelbrot.cpp
│
├── CMakeLists.txt
└── README.md
Собственная реализация математических примитивов (расскажу чуть подробнее лишь про один):
-
Complex— комплексные числа Поддерживает:- алгебраическую и тригонометрическую формы (именованные конструкторы)
- арифметические операции (+, −, *, /)
- модуль, аргумент (нормализован), взятие сопряженного
- возведение в степень
- извлечение n-корней
- сравнение с учётом EPS
- форматированный вывод через
std::format - широко используются
constexprи[[nodiscard]]
-
Quaternion -
Vec3 -
Ray
Это ядро может использоваться независимо от фракталов — как мини-библиотека для численных и графических задач.
Реализован собственный минималистичный модуль для работы с 24-bit BMP:
- Загрузка и сохранение BMP без сторонних библиотек
- Поддержка только:
- 24 bpp
- без сжатия (BI_RGB)
- Явная работа со структурами заголовков BMP
- Контроль над выравниванием структур через
#pragma pack
Универсальное представление растрового изображения:
Bmp image = Bmp::empty(1920, 1080);
image.set_pixel(x, y, {b, g, r});
Bmp image2 = Bmp::empty(4000, 4000, colors::WHITE);
BgrPixel pixel = image2.get_pixel(12, 122);
image2.try_set_pixel(-10, 1, {b, g, r}); // no exception, returns true if setРешил, что будет правильно вынести логику загрузки и выгрузки bmp файлов из класса, этим стремлюсь соблюдать принцип Single Responsibility.
Bmp image = io::load("some/interesting/path");
// преобразования
io::save(image, "some/unique/path");Обобщённый движок рендеринга фракталов не зависит ни от формата изображения, ни от конкретной формулы фрактала — оба аспекта задаются снаружи через обобщённые параметры:
| Компонент | Отвечает за |
|---|---|
IterationFunc |
Формула итерации (например, z = z² + c) |
InitialFunc |
Начальное значение z_0 |
ParamFunc |
Параметр фрактала (например, c для Julia) |
Colorizer |
Преобразование числа итераций → цвет |
Это позволяет строить:
- множество Мандельброта
- множества Жюлиа
- кастомные фракталы с любыми формулами
Используется C++ concepts для задания требований к colorizer-а:
template <typename Colorizer>
concept ColorizerConcept = requires(Colorizer c, double mu, int max_iter) {
typename Colorizer::pixel_type;
{ c(mu, max_iter) } -> std::same_as<typename Colorizer::pixel_type>;
};Рендерер не знает ничего о формате изображения — только о том, что есть pixel_type (так как они могут быть произвольные, в нашем случае для Bmp используется bgr-формат).
Это позволяет использовать любой тип изображения, удовлетворяющий концепту PixeledImage.
Добавлена система ключевых кадров:
struct FractalKeyframe {
Viewport viewport;
FractalConfig config;
math::Complex julia_c;
};Поддерживается интерполяция между состояниями:
FractalKeyframe k = interpolate(a, b, t);Это основа для генерации зум-анимаций и морфинга фракталов.
Рендерер работает с любым типом изображения, удовлетворяющим:
template<typename Image>
concept PixeledImage = requires(Image image, int x, int y, Image::pixel_type pixel) {
typename Image::pixel_type;
{ image.width() } -> std::convertible_to<int>;
{ image.height() } -> std::convertible_to<int>;
{ image.set_pixel(x, y, pixel) };
};Это полностью отделяет логику фрактала от способа хранения и вывода изображения.
Минималистичный потокобезопасный логгер:
- Уровни:
INFO,WARN,DEBUG,ERROR - Цветной вывод в консоль
- Форматирование через
std::format - Защита через
std::mutex
LOG_INFO("Rendering started: {}x{}", width, height);Можно полностью отключить через макрос LOGGING_ENABLED, когда нужна большая производительность.
- C++20/23
- Concepts
- Templates
- OpenMP
- CMake
- GoogleTest
Проект покрыт unit-тестами на базе GoogleTest:
- математические классы (Complex, Quaternion, Vec3)
- классы работы с Bmp
✔ Разделение математики, рендеринга и вывода ✔ Минимальные зависимости ✔ Обобщённый дизайн через concepts ✔ Расширяемость через функции высшего порядка ✔ Чёткий контроль над бинарными структурами ✔ Подходит как база для:
- фрактальных визуализаторов
- CPU-рендереров
- учебных проектов по численным методам
- Поддерживается только 24-bit BMP без сжатия
- Выравнивание структур ориентировано на little-endian архитектуры (типично x86)
- Рендеринг выполняется на CPU
- GPU-рендеринг (CUDA / OpenCL)
- Мультипоточный тайлинг
- Интерактивный viewer с возможностью подвигать ползунки (SDL / ImGui)
- Поддержка 3D-фракталов с использованием кватернионов

