ГоловнаСтаттіVFX

Стабільні Рідини: Як Ігри Моделюють Дим в Реальному Часі

Переміщуйте мишу, щоб ін'єктувати дим у розв’язувач стабільних рідин Джо Стама та спостерігайте, як обмеження віртності змушує його згортатися у спіральні стоrmi.

mysimulator teamОновлено — червень 2026≈ 9 хв читання▶ Відкрити симуляцію

Чому наивні розчинники рідин вибухають

Рівняння Навіє-Стокса описують рух незмісних рідин, а традиційний спосіб чисельного моделювання їх за допомогою є алгоритм явного кінцевих різниць: просувати швидкість вперед на невеликий крок часу, використовуючи поточні похідні поля. Явні схеми, такі як ця, стабільними є лише тоді, коли крок часу залишається нижче межі, встановленої умовою CFL — приблизно нічого не може пройти більше одного комірки сітки на крок, і дотримання цього обмеження при реальних частотах кадрів вимагало б сотень підкроків на кадр для будь-якої розумно тонкої сітки. Стабільність рідин Джосса Стама в його статті SIGGRAPH 1999 «Stable Fluids» досягається безпосередньо, оскільки він замінює пряме інтегрування швидкості чимось, що не може вибухнути — інтерполяцією.

жива демонстрація · пов'язана симуляція● LIVE

Вирішення у три кроки

Кожен кадр симуляції Stable Fluids запускає одну й ту ж короткий контур на своїй швидкості-полі: застосовувати зовнішні сили, переміщувати поле вздовж себе та потім коригувати його так, щоб маса зберігалася.

addForce(w, dt)     // buoyancy, an injected smoke source, wind
advect(w, w, dt)    // semi-Lagrangian: trace back, bilinear sample
project(w)          // enforce ∇·w = 0 — incompressibility

Напівлагрангове перенесення: торгівля точністю заради стабільності

Замість того, щоб запитувати "Куди має перейти вміст цієї комірки?", напівлагрангове перенесення ставить протилежне питання для кожної комірки: "Звідки взявся вміст цієї комірки?" Воно відстежує віртуальну частинку назад через поточне поле швидкості за один часовий крок, а потім зчитує значення попереднього кадру в цій точці за допомогою білінійного семплювання:

Для кожної комірки x: x0 = x - dt * velocity(x) // Відстеження назад на один часовий крок q(x) = bilinearSample(q_prev, x0) // Читання попереднього поля там Оскільки оновлення є лише зразком існуючого поля, воно не може підсилити значення вище того, що було вже присутнім — немає зворотного зв’язку для розповсюдження помилки, тому метод безумовно стабільний незалежно від того, наскільки великий часовий крок. Ціна - чисельне дифузія: білінійне семплювання тихо усереднює найдрібніші деталі на кожному кроці, тому змодельоване диму розмивається та втрачає чіткість структури швидше, ніж справжній дим.

for each cell x:
  x0    = x - dt * velocity(x)        // trace backward one time step
  q(x)  = bilinearSample(q_prev, x0)  // read the previous field there

Послідовність проектування: робимо це незмінюваним

Голомодезаком Гельмгольца стверджується, що будь-який векторний потік можна розкласти на частину з нульовою дивергенцією та градієнт скалярного поля. Послідовність проектування безпосередньо використовує це: вона розв’язує рівняння Пуассона для скалярного поля тиску, а потім віднімає градієнт цього тиску з полів швидкості, залишаючи результат із нульовою дивергенцією — дискретний еквівалент «жодного об'єму рідини не створюється або не знищується в жодній точці».

∇²p = ∇·w // Рівняння Пуассона для тиску w = w - ∇p // віднімання градієнту тиску → векторний потік з нульовою дивергенцією Рівняння Пуассона розв’язується ітеративно на сітці — стандартні методи Гаусса-Зеіделя або Якобі, зазвичай достатньо 20 до 40 ітерацій для візуально стабільного диму з незмінюваною швидкістю при інтерактивних частотах кадрів.

∇²p = ∇·w        // Poisson equation for pressure
w   = w - ∇p     // subtract the pressure gradient → divergence-free velocity

Отримання звислотипного руху: обмеження вихлюпу

Одна справжня вартість цієї стабільної, дифузійної схеми полягає в тому, що тонкі спіралі віхлюпів, які розвиваються справжній димний стовп, згладжуються повторним інтерполюванням, залишаючи результат виглядати плоским і липким замість турбулентного. Техніка обмеження вихлюпу 2001 року від Федківа, Стама та Дженсена вимірює місцевий хід поля швидкості, а потім додає невелику штучну силу, яка штовхає рідину до областей з більшою величиною магнітуди вихлюпу — навмисно повторно впроваджуючи обертальну енергію, яку чисельний метод безперервно розсіює, без необхідності значно більш детальної, набагато дорожчої сітки.

ω      = ∇ × w                       // vorticity — the curl of velocity
N      = ∇|ω| / |∇|ω||               // normalised gradient of vorticity magnitude
f_conf = ε * (N × ω)                 // confinement force added back into w

Чому цей метод все ще домінує в реальному часі VFX

Необхідна стабільність на великих кроках часу та грубій сітці є тим, що робить можливим інтерактивний дим і вогонь у іграх і демо-версіях у браузері з частотою 60 кадрів в секунду. Офлайн-виробництво фільмів, використовуючи розв’язувачі FLIP Houdini або на основі частинок, працює з набагато вищою роздільною здатністю та більш фізично точними схемами, оскільки не потрібно дотримуватися бюджету реального часу. Але той самий базовий рецепт — напів-лагрангова адвекція, проектування тиску та утримання вироту — при більш високій роздільній здатності та з більшою кількістю кроків підрозділу все ще лежить в основі більшості GPU-розв’язувачів диму та вогню, які використовуються сьогодні в виробництві, більше ніж за два десятиліття після оригінальної статті Стама.

Часті запитання

Чому напівлагранжева адивка не має умовного нестабільного характеру?

Вона ніколи не інтегрує вперед-різницевого рівняння, яке може розійтися. Замість цього вона відстежує кожну клітинку назад через поле швидкості та інтерполює значення попереднього кадру в цій точці, а інтерполяція може лише усереднювати існуючі значення, ніколи їх не збільшувати, незалежно від того, наскільки великий крок часу.

Чому симуляційне дим виглядає м'якшим за реальний дим?

Кожен напівлагранжевий крок пересемплює поле за допомогою білінійної інтерполяції, що трохи більше згладжує дрібні деталі з кожним кадром — це чисельний побічний ефект, який називається штучним розмиттям. Конфігурація ворітності вводить частину цієї втраченої спіральності назад, але вона лише частково компенсує розмивання.

Що насправді забезпечує етап проекції?

Неспальність. Він вирішує рівняння Пуассона для скалярного поля тиску та віднімає його градієнт із поля швидкості, залишаючи результат із нульовим дивергентом — що відповідає фізичній реальності, що газ або рідина зазвичай не стискається чи розширюється локально в типових симульованих умовах.

Спробуйте наживо

Усе, що вище, працює прямо у вашому браузері — відкрийте Smoke VFX — Stable Fluids і змінюйте параметри під час роботи. Нічого не встановлюється, нічого не завантажується на сервер, уся модель живе в одній вкладці.

▶ Відкрити симуляцію Smoke VFX — Stable Fluids

Що ви знайшли?

Додати кроки відтворення (опційно)