Открыть

AVRlabs · движок

Quasar

Движок, на котором работает Fractal Forge. В нём нет ни одного полигона: каждый пиксель — луч, который по формуле расстояния ищет поверхность фрактала. Всё считает ваша видеокарта, сервер только отдаёт файлы.

Готовлю шейдер…

Квазар — ядро далёкой галактики, один из самых ярких объектов во Вселенной: его видно сквозь миллиарды световых лет. Лучи движка тоже идут сквозь бесконечную глубину и возвращаются со светом. Имя стоит в одном ряду с Apogee и Pulsar — другими системами avr.

11формул: бульбы, боксы, IFS, кватернионы и гибриды
33шейдерные программы, собираются из одного исходника
0зависимостей: ни three.js, ни GLFW, ни ImGui
10−12предел погружения в Windows-версии с fp64
57 / 57контрольных сидов дают одно и то же в вебе и в C++
700 КБвесь exe вместе с интерфейсом и шейдерами
01

Фрактал — это формула, а не модель

Точка пространства принадлежит фракталу, если итерация из неё не улетает в бесконечность. У Мандельбульба итерация — это «возведение в степень» в сферических координатах: радиус возводится в степень n, углы умножаются на n, и прибавляется исходная точка c.

r = |z|,  θ = acos(zz / r),  φ = atan(zy, zx)
z ← rⁿ · (sin nθ · cos nφ,  sin nθ · sin nφ,  cos nθ) + c

Для степени 8, самой частой, Quasar обходится без тригонометрии: z⁸ раскрыт в полином от координат, и шейдер не вызывает ни acos, ни pow. Остальные формулы устроены похоже. Мандельбокс складывает пространство кубом и сферой, KIFS отражает его плоскостями, как калейдоскоп, кватернион Жюлиа итерирует q² + c в четырёх измерениях. Гибрид чередует до четырёх разных формул внутри одной итерации.

02

Трассировка сферами

Поверхность фрактала нельзя пересечь с лучом аналитически. Зато можно оценить, насколько далеко до неё из любой точки, — это и есть оценка расстояния (distance estimator). Луч шагает ровно на эту величину: в шар такого радиуса фрактал не заходит, значит перепрыгнуть поверхность нельзя.

DE(c) = ½ · ln r · r / |dr|,   dr ← n · rⁿ⁻¹ · dr + 1

Попробуйте сами. Это двумерный Мандельброт и та же самая формула. Перетащите звезду-камеру, кликните, куда светить. Круги — безопасные шаги луча. Возле границы они мельчают, и луч сходится к поверхности.

Шагов: —Перетащите звезду или кликните по полю

В 3D всё то же, только шагов до 320 на пиксель, и каждый шаг — десятки итераций формулы. Чтобы на неточной оценке луч не проскочил тонкую стенку, шаг умножается на запас: 0,9 для бульбов, 0,95 для боксов и 1,0 для IFS, у которых оценка точная.

03

Точность размером с пиксель

Когда остановиться? Если требовать фиксированную точность, вдали появится шум, а вблизи пропадут детали. Quasar считает, что луч попал, когда расстояние меньше половины пикселя на этой глубине: ε = 2·tan(fov/2) / H · t. Это конус пикселя: чем дальше, тем грубее, и рябь не появляется.

По той же причине число итераций растёт с зумом. Каждое двукратное приближение добавляет итерации по коэффициенту формулы: для IFS это около 1 / log₂(масштаба), то есть ровно столько, чтобы новая итерация давала детали размером в пиксель. Лишние итерации только добавили бы рябь.

04

Свет

05

Кадр, который дочищается сам

Один кадр — один луч на пиксель. Пока камера стоит, Quasar добавляет новые сэмплы со сдвигом внутри пикселя по последовательности Халтона (2, 3) и усредняет их в буфере RGBA16F: сглаживание, мягкие тени и глубина резкости появляются сами. Буферы чередуются по схеме ping-pong, и копируется только изменившийся прямоугольник.

В движении кадр смешивается с предыдущим на 55%, поэтому картинка не мерцает. Предварительный проход в ¼ разрешения конусом находит, где начинается поверхность, и основной луч стартует сразу оттуда. Это даёт от 6 до 17% скорости бесплатно.

06

Глубже, чем позволяет float

У float 24 бита мантиссы. На зуме около 10⁵ соседние пиксели получают одинаковые координаты, и картинка рассыпается на квадраты. В WebGL двойной точности нет, поэтому веб-версия останавливается там.

Windows-версия считает в double, но хитро. На игровых видеокартах double в 32–64 раза медленнее float, поэтому точность смешанная: double нужен, только пока орбита не «растянула» разницу между соседними пикселями (dr · ε > 10⁻⁴), дальше итерации досчитываются во float. На RTX 4060 кадр на ×10⁹ дочищается за 15–20 секунд; целиком в double это заняло бы в разы больше.

Тяжёлый кадр рисуется полосами по ~35 мс. Иначе Windows решила бы, что видеокарта зависла, и через 2 секунды сбросила бы драйвер (TDR). Предел — около 5·10⁻¹²: дальше кончается уже и double.

07

Сид — это вселенная

Название вроде iron_comet_sigma97 превращается в фрактал детерминированно: SHA-256 от строки даёт 32 байта, и каждый байт отвечает за свою ручку.

h = sha256("seedmap_v3:" + seed)       // 32 байта
power   = [8,8,8,7,9,6,10,5,4,12,3,11][h[15] % 12]
palette = palettes[h[4] % palettes.length]
yaw     = lerp(0, 360, h[7] / 255)
dist    = fit · lerp(0.95, 1.2, h[9] / 255)

Этот код есть дважды: на JavaScript для веба и на C++ для Windows. Автотест прогоняет 57 контрольных сидов через обе реализации, и параметры совпадают все до одного. Поэтому пресет, ссылка или PNG из браузера открываются в Windows-версии тем же фракталом. Сам пресет зашит в PNG отдельным блоком iTXt, так что картинка — это и есть файл сохранения.

08

Генетика формул

Мутация сдвигает гены — степень, масштаб, константы Жюлиа, складки, повороты, палитру, металл — на гауссов шум. Генератор случайных чисел — mulberry32, зерно которого берётся из SHA-256 родителя, поэтому одна и та же мутация воспроизводима. Иногда случается большая мутация: фрактал получает вторую формулу и становится гибридом.

Скрещивание двух фракталов одного типа смешивает их числа. Если типы разные, потомок становится гибридом, и его звенья по шаблону AB, AAB, ABB или ABAB берутся по очереди от обоих родителей. Так Мандельбокс и Менгер дают существо, которого нет ни в одном каталоге.

09

Одни шейдеры — две программы

ВебWindows
ГрафикаWebGL2, GLSL ES 3.0OpenGL 4.3 core, свой загрузчик функций
ЯзыкJavaScript без сборщикаC++17, Win32 и WGL
ИнтерфейсHTML и CSS в стиле avrсвой immediate-mode UI с атласом шрифта из GDI
Глубина~10⁵~10¹², fp64 со смешанной точностью
ЭкспортPNG до 4096², видео, меш OBJ и PLYPNG до 8K через WIC
Особоеэволюция сеткой, музыка, VR, обоизаставка Windows, 0% нагрузки в покое

Шейдеры пишутся один раз, в веб-версии. При сборке Windows-версии скрипт вшивает их в exe, а при запуске заголовок #version 300 es меняется на #version 430 core. Исправление в формуле сразу попадает в обе программы.

Fractal Forge для Windows

Самая глубокая версия

Погружение до 10⁻¹², экспорт до 8K и заставка Windows. Архив 610 КБ, установка не нужна: распакуйте и запустите FractalForge.exe.

  • Windows 10 или 11, 64 бит
  • Видеокарта с OpenGL 4.3 — почти любая с 2012 года
  • Для fp64-погружения — double в шейдерах (GL_ARB_gpu_shader_fp64): NVIDIA или AMD

Заставка: правый клик по FractalForge.scr → «Установить».

Для любителей командной строки:

FractalForge.exe --seed iron_comet_sigma97 --type menger
FractalForge.exe --shot out.png --samples 256 --hide-ui
FractalForge.exe --dive --dive-until 1e-9 --deep

Windows может предупредить о неизвестном издателе: у программы нет платной подписи кода. «Подробнее» → «Выполнить в любом случае».