3D-фрактали: Mandelbulb, губка Менгера та рендеринг через поля відстаней
Перехід від 2D- до 3D-фракталів не є простим — не існує коректного 3D- аналога комплексних чисел, який зберігав би всю алгебру. Та попри це надзвичайно багаті структури, як-от Mandelbulb та губка Менгера, виникають із простих правил. Ця стаття розкриває математику обох підходів, пояснює ray-marching полів знакових відстаней і наводить код шейдера GLSL для дослідження в реальному часі.
1. Чому 3D-фрактали складні
Множина Мандельброта живе на комплексній площині й визначається ітерацією z→ z² + c. У 2D піднесення до квадрата — це просто множення комплексних чисел: (a + bi)² = a² − b² + 2abi. Ключова властивість, завдяки якій це працює фрактально, — аналітичність: похідна існує й задовольняє рівняння Коші–Рімана, тобто відображення є конформним (зберігає кути) і породжує нескінченно складні самоподібні межі.
Природне розширення на три виміри потребувало б нормованої алгебри з діленням над ℳ. By Hurwitz's Гурвіца така алгебра не існує — єдині коректні нормовані алгебри з діленням мають розмірність 1, 2, 4 (кватерніони) або 8 (октоніони). Кватерніони дають 4D-фрактал (кватерніонну множину Жюліа / Мандельброта), але проєкція його назад у 3D дає відносно гладкі форми без складної бульбоподібної структури, на яку ми очікуємо.
Існує два успішні підходи:
- Алгебраїчні хитрощі — визначити операцію «степеня» над 3D-векторами через сферичні координати (підхід Mandelbulb), жертвуючи справжньою алгебраїчністю, але досягаючи візуально вражаючих результатів.
- Геометрична ітерація — багаторазово застосовувати афінні перетворення чи перетворення складання у 3D (губка Менгера, Mandelbox), що взагалі не потребує жодної алгебраїчної структури.
Рендеринг цих неявних 3D-об'єктів у реальному часі стає практичним завдяки ray-marching полів знакових відстаней, який використовує функції-оцінювачі відстані, виведені з ітерації фрактала за часом виходу (escape-time).
2. Mandelbulb: формула сферичного степеня
Mandelbulb запропонували Деніел Вайт і Пол Найландер у 2009 році. Ідея полягає в тому, щоб подати 3D-точку v = (x, y, z) у сферичних координатах (r, θ, φ), піднести її до n-го степеня, помноживши радіус n разів і помноживши кути, а потім перетворити назад:
Тоді ітерація Mandelbulb має вигляд z → z^n + c (у наведеному вище 3D-сенсі) починаючи з zâ‚€ = 0. Точка c належить множині, якщо |z| залишається обмеженим. Канонічний вибір — n = 8, що дає складні бульбоподібні структури з аналогами «слонячої долини» та «долини морського коника».
Чому n = 8?
Для n = 2 результат схожий на гладку кулю — нецікаво. Зі збільшенням n поверхня набуває дедалі більше самоподібних деталей. При n = 8 фрактал демонструє переконливий 3D-аналог множини Мандельброта з глибоко вкладеними спіральними елементами й багатою межею, чия гаусдорфова розмірність оцінюється приблизно в 2,97 — майже заповнює простір.
Обмеження
Оскільки сферичний степінь не підкоряється правилу добутку для похідних у справжньому алгебраїчному сенсі (це не голоморфне відображення), Mandelbulb не є справжньою 3D-множиною Мандельброта. Внутрішні області та межа не мають тих самих математичних гарантій, що й у 2D- випадку, та візуально й обчислювально це один із найбільш вдячних відомих 3D-фракталів.
Оцінювач відстані
Щоб виконувати ray-marching Mandelbulb, нам потрібен оцінювач відстані (DE) — нижня межа відстані від точки до поверхні фрактала. Виводиться з величини похідної вздовж ітерації:
Це формула Іньїго Квілеза. Вона дає консервативну (із заниженням) межу відстані — завжди безпечно крокувати на частку (зазвичай 0,8–0,99) від DE, щоб запобігти проходженню крізь тонкі елементи.
3. Губка Менгера: система ітерованих функцій у 3D
Губку Менгера будують, починаючи з одиничного куба й рекурсивно ділячи його на сітку 3×3×3 з 27 підкубів, а потім вилучаючи центральний куб і 6 кубів у центрах граней (залишаючи 20 підкубів) і повторюючи процес для кожного підкуба, що залишився.
Після k ітерацій губка має 20^k кубів, кожен зі стороною (1/3)^k. Її гаусдорфова розмірність:
Губка має нульовий обʼєм (у границі), але нескінченну площу поверхні — характерна властивість фракталів із розмірністю між 2 і 3.
SDF для губки Менгера (підхід зі складанням)
Губку Менгера можна обчислити за допомогою SDF зі складанням, що відтворює рекурсивну побудову без розгалужень:
Сортування (обміни xy, xz, yz) складають точку в канонічний октант на кожному рівні, а масштабний коефіцієнт накопичується за правилом ланцюга, так само як і в DE для Mandelbulb.
Порівняння підходів
- Escape-time (Mandelbulb): підходить для фракталів, заданих ітерацією на кшталт комплексної; природне згладжене розфарбовування через orbit traps.
- Ітеративне складання (Менгер, Mandelbox): підходить для фракталів, заданих афінними відображеннями; зазвичай дешевше обчислювати на крок.
- Обидва дають коректний DE для sphere-tracing; вибір суто означальний.
4. Поля знакових відстаней та ray marching
Поле знакових відстаней (SDF) — це скалярна функція f(p), що повертає знакову відстань від точки p до найближчої поверхні: відʼємну всередині, додатну ззовні, нуль на поверхні. Ray marching (sphere tracing) використовує SDF, щоб безпечно просувати промінь:
- Випустити промінь із початку камери o у напрямку d (нормованому).
- У поточній позиції p обчислити SDF: t = f(p).
- Стрибнути вперед на t уздовж променя: p += t · d.
- Повторювати, доки |t| < ε (влучання) або накопичена відстань > max_dist (промах).
Оцінювання нормалі
Нормалі до поверхні обчислюють через градієнт SDF за допомогою скінченних різниць:
Це потребує 6 обчислень SDF на влучання. Скінченні різниці на основі тетраедра різниці на основі тетраедра (трюк Квілеза) скорочують це до 4 обчислень, зберігаючи точність.
Питання продуктивності
- MAX_STEPS — домінантна вартість. Тонкі фрактальні елементи потребують багатьох кроків; типовий діапазон 64–256.
- Розмір кроку можна множити на коефіцієнт релаксації ω > 1.0 (надрелаксація / «покращений sphere tracing»), щоб зменшити кількість кроків у відкритих областях, перевіряючи на відкат, коли промінь перестрибує.
- Обмежувальні обʼєми (наприклад, сфера радіуса 1,2 навколо фрактала) дешево відсікають фонові пікселі.
5. SDF-оцінювачі відстані для фракталів
Для escape-time фракталів DE виводять із модуля похідної вздовж орбіти. Загальна формула для відображення z → f(z), що починається в c:
Ключова тонкість: DE потрібно розділити на накопичений масштабний коефіцієнт для фракталів на основі складання. Для губки Менгера кожна ітерація множить координати на 3, тож DE ділять на 3^ITERATIONS. Якщо про це забути, форма виглядатиме геометрично правильною, але з нормалями, спрямованими у випадкові напрямки, — поширений головний біль при налагодженні.
Ambient occlusion з кількості кроків
Дешева, але ефективна оцінка ambient occlusion — це кількість зроблених кроків ray-marching, поділена на MAX_STEPS. Області, що потребують багатьох дрібних кроків (поблизу глибоких щілин), темніші; відкриті пласкі області (мало кроків) світліші. Це коректно затемнює фрактальні фіорди та глибокі складки без додаткових променів.
6. Розфарбовування orbit-trap та згладжений лік ітерацій
Згладжений лік ітерацій
Сирий лік ітерацій escape-time є цілим числом, що породжує помітні смуги на відрендереному зображенні. Згладжене розфарбовування замінює індекс смуги n дійсним значенням:
Ця формула походить із теорії потенціалу множини Мандельброта: функція Гріна G(c) = lim log|z_n| / 2^n неперервна через межі смуг. Поправка logâ‚‚(logâ‚‚(r)) усуває цілочислові сходинки.
Orbit traps
Orbit traps розфарбовують точку залежно від того, наскільки близько орбіта проходить до геометричної фігури:
- Точкова пастка: записати min(|z − trap_point|) уздовж орбіти. Зіставити цей мінімум із кольором.
- Площинна пастка: мінімальне абсолютне значення однієї координати за всіма ітераціями.
- Хрестова пастка XY: min(|x|, |y|) — дає яскраві хрестоподібні кольорові візерунки.
- Кругова пастка: min | |z| − r_trap | — дає кільцеві візерунки навколо внутрішніх елементів.
Кілька пасток можна змішувати за зваженим мінімумом або відстежуючи, яка пастка спрацювала на найближчому наближенні. Результат значно багатший за просте градієнтне розфарбовування.
Освітлення на основі нормалей
Щойно відомі точка влучання та її нормаль, безпосередньо застосовується стандартне затінення Фонга або Блінна–Фонга. Додавання дзеркального відблиску з показником 64–128 значно посилює сприйняття складної поверхні. Мʼякі тіні можна апроксимувати, просуваючи вторинний промінь до джерела світла й відстежуючи, наскільки близько він підходить до поверхні (техніка напівтіні «м'якості тіні» від Квілеза).
7. Ray-marcher на GLSL: повний шейдер
Нижче наведено самодостатній фрагментний шейдер GLSL для Mandelbulb у восьмому степені. Він працює у WebGL 1.0 з відповідними підказками точності.
// ── Mandelbulb Ray-Marcher (GLSL ES 3.0) ──────────────────────────
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
const int ITER = 8;
const int STEPS = 120;
const float BAILOUT = 4.0;
const int N = 8;
// Distance estimator for Mandelbulb power-8
float mandelbulbDE(vec3 pos) {
vec3 z = pos;
float dr = 1.0, r = 0.0;
for (int i = 0; i < ITER; i++) {
r = length(z);
if (r > BAILOUT) break;
float theta = acos(clamp(z.z / r, -1.0, 1.0));
float phi = atan(z.y, z.x);
dr = pow(r, float(N - 1)) * float(N) * dr + 1.0;
float zr = pow(r, float(N));
z = zr * vec3(
sin(float(N)*theta) * cos(float(N)*phi),
sin(float(N)*theta) * sin(float(N)*phi),
cos(float(N)*theta)
) + pos;
}
return 0.5 * log(r) * r / dr;
}
// Finite-difference normal (tetrahedron method)
vec3 calcNormal(vec3 p) {
const vec2 k = vec2(1.0, -1.0) * 5e-4;
return normalize(
k.xyy * mandelbulbDE(p + k.xyy) +
k.yyx * mandelbulbDE(p + k.yyx) +
k.yxy * mandelbulbDE(p + k.yxy) +
k.xxx * mandelbulbDE(p + k.xxx)
);
}
// Sphere-trace
float trace(vec3 ro, vec3 rd) {
float t = 0.0;
for (int i = 0; i < STEPS; i++) {
float d = mandelbulbDE(ro + t * rd);
if (d < 1e-4) return t;
t += d * 0.8;
if (t > 8.0) break;
}
return -1.0;
}
void main() {
vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution) / u_resolution.y;
// Orbiting camera
float angle = u_time * 0.3;
vec3 ro = vec3(2.5 * sin(angle), 0.5, 2.5 * cos(angle));
vec3 ta = vec3(0.0);
vec3 ww = normalize(ta - ro);
vec3 uu = normalize(cross(ww, vec3(0, 1, 0)));
vec3 vv = cross(uu, ww);
vec3 rd = normalize(uv.x * uu + uv.y * vv + 1.5 * ww);
float t = trace(ro, rd);
vec3 col = vec3(0.05, 0.05, 0.08); // background
if (t > 0.0) {
vec3 p = ro + t * rd;
vec3 n = calcNormal(p);
vec3 lig = normalize(vec3(0.8, 0.6, 0.4));
float diff = clamp(dot(n, lig), 0.0, 1.0);
float spec = pow(clamp(dot(reflect(-lig, n), -rd), 0.0, 1.0), 64.0);
float trap = clamp(0.1 / abs(p.x * p.y), 0.0, 1.0);
vec3 baseCol = mix(vec3(0.1, 0.2, 0.8), vec3(0.9, 0.4, 0.1), trap);
col = baseCol * diff + vec3(0.5) * spec;
col *= 0.8 + 0.2 * (1.0 - t / 8.0);
}
gl_FragColor = vec4(pow(col, vec3(0.4545)), 1.0);
}
iResolution → із u_resolution, а
iTime — → з u_time. Змінюйте константу
N від 2 до 12, щоб спостерігати трансформацію «бульби».
8. Розширення: Mandelbox, Juliabulb та складання простору
Mandelbox
Mandelbox (Том Лоу, 2010) замінює сферичний степінь на складання за кубом з подальшим складанням за сферою:
Mandelbox породжує нескінченно вкладені кубоподібні структури — рекурсивні коридори, силуети міст, фрактальні корали. Параметр scale (зазвичай від −2,0 до −1,5) визначає загальний характер; значення близько −1,5 дають тонкі папоротеподібні структури, тоді як −2,0 дає масивні кутасті скелі.
Juliabulb
Подібно до того, як 2D-множина Жюліа фіксує c і варіює zâ‚€, Juliabulb фіксує 3D-параметр c і використовує різні початкові точки. Це вирізає іншу область простору параметрів, породжуючи виразно симетричні форми. Анімація c уздовж шляху створює фрактальні анімації з трансформацією.
Клейнові групи та фрактали інверсії за сферою
Загальніші фрактали складання застосовують перетворення Мöbius transformations — інверсії через сфери — рекурсивно. Повʼязані з 3D клейновими граничними множинами та гіперболічною геометрією, вони дають напівпрозорі фрактали-скупчення бульбашок із точним DE, який виводиться з правила ланцюга.
Гібридні фрактали
Чергування кроків ітерації з різних формул — один крок Mandelbulb, потім один крок складання за кубом — створює «гібридні» фрактали з цілком новими морфологіями. Більшість прославлених онлайн-рендерів фракталів — це саме такі гібриди, що використовують безмежну компонованість оцінювачів відстані.