Emityr, basen i wiele zmarłych cząsteczek
Każdy system cząsteczkowy zaczyna od tego samego szkieletu. Emityr tworzy nowe cząsteczki w pewnym tempie z wykorzystaniem kształtu źródła — punktu, stożka, dysku. Każda cząsteczka otrzymuje pozycję, prędkość, czas życia i ziarno losowe, a następnie jest wprowadzona do ustalonego rozmiaru basenu. W każdym klatce całe basen jest zaktualizowane: uzupełnia się wiek każdej cząsteczki, integruje się jej ruch, a jeśli jej wiek przekracza czas życia, oznacza się ją jako zmarłą i emityr powtarza slot. Nic tu nie jest unikatowe dla efektów specjalnych — to dokładnie pętla aktualizacji z ustalonym tablicowym rozmiarem używana przez dowolny system cząsteczkowy na tej stronie — różnice między nudnym brązowym lawem a przekonającym ogniem są całe w warunkach per-cząsteczce, które zostają nałożone na nie.
Krzywe okresu życia: tajemnica przekonającego ognia
Przeczytny ognisko jest jasnoniebiesko-złotym na dole, zmienia się w odcień czerwonożółty i kończy się jako półprzeźroczysta dymka. Cząsteczki osiągają to efektem krzywej normalizowanego okresu życia — funkcji t = wiek / okres życia, od 0 (urodzenie) do 1 (zmiana), która steruje kolorzem, rozmiarem i przejrzystością osobno:
t = wiek / okres życia // 0 przy urodzeniu, 1 przy zmianie color = gradient(t) // biały -> żółty -> czerwonoczółty -> ciemny czerwony -> szarą dymkę size = lerp(startSize, endSize, t) * (1 + drgota(t)) alpha = fadeInOut(t) // szybko zwiększa się, wolno wygasza blisko t=1 Gwarki używają tej samej maszyny, ale z znacznie krótszym okresem życia i krzywej koloru, która pozostaje blisko biało-czerwonego aż do momentu nagle przekształca się w czarny, ponieważ metal ciepły szybko chłodzi się i zatrzymuje emisję światła widzialnego. Ogień używa dłuższego okresu życia, bardziej losowej początkowej prędkości w górę, oraz rozmiaru, który rośnie po jego życiu, aby sugestować rozszerzający się ciepły gaz, podczas gdy gwarki zanikają i znikają.
t = age / lifetime // 0 at birth, 1 at death color = gradient(t) // white -> yellow -> orange -> dark red -> smoke grey size = lerp(startSize, endSize, t) * (1 + wobble(t)) alpha = fadeInOut(t) // ramps up fast, fades out slowly near t=1
Zmieszewanie dodawane: dlaczego ogień wydaje się świecić
Normalna transparencja łączy kolor cząsteczki z tłem za nią. Zmieszewanie dodawane natomiast sumuje wartości koloru bezpośrednio na bufor ramek: wynik = tło + kolorCzasteczki * alpha, bez odejmowania. Gdzie wiele jasnych cząsteczek nakładają się, ich kolory nadal dodatkują się do siebie aż piksel osiągnie biały puro, co dokładnie jak na rzeczywistość, gdzie nawiązywane źródła światła zacieśniają się. To powoduje, że grupa nakładających się embers czyta się jako jedno jasne świecenie zamiast stosu widocznych przepuszczalnych dysków — a dlatego użycie go dla dymu wygląda nieprawidłowo, ponieważ dym akceptuje światło zamiast go wydawać i potrzebuje standardowego zmieszewania transparancji zamiast tego.
Słabe dźwięki gwałtowności: tlenko bez rozwiązywania dynamicznej płynności
Dziwny ogień i dym są zarządzane równaniami Naviera-Stokesa, które są zbyt drogie do rozwiązania na partiklu po partikułu w tempie 60 klatek na sekundę dla gry lub rzeczywistego podglądu. Standardowa sztuczka to curl noise: uziarnienie pola Perlin 3D i obliczenie jego curl (∇ × pole) do uzyskania nowego pola wektorowego, które jest konstruktivamente bez źródeł ani chłodników — co oznacza, że cząstki przemieszczające się przez to pole kręcą się i tworzą eddy bez nigdy skupienia się w nieprzyrodzonej gromadzie czy zanikania do dziury. Każda cząstka prosi o próbkowanie pola curl na swoim położeniu w każdej klatce i dodanie skalowanego wykazu do swojej prędkości, co tworzy gwałtowne, krążące ruch, który wygląda prawidłowo płynny dla ułamka kosztu rzeczywistego solvera płynności.
velocity += gravity * dt velocity += curlNoise(position, time) * turbulenceStrength * dt velocity *= (1 - drag * dt) position += velocity * dt
Sortowanie, głębokość i przyspieszenie GPU
Cząsteczki przezroczyste muszą być rysowane od tyłu do przodu, aby poprawnie zlokalizować, co oznacza sortowanie całego puli według odległości od kameru na każdym klatce — koszt O(n log n), który staje się realny dla setek tysięcy cząsteczek. Efekty dodawanej kombinacji, takie jak ogień i błyskawice, otrzymują tu wolne przejście: ponieważ dodawanie jest komutatywne, kolejność rysowania nie zmienia końcowego koloru, więc gry pomijają sortowanie dla emiterów dodawanych i płatną tylko za koszt rysowania dla cząsteczek z alpha-blendem, takich jak dym i pył. Modernne silniki gier przepinają całą pętlę symulacji na GPU jako shader obliczeniowy, aktualizując setki tysięcy cząsteczek w paralelu — CPU tylko emituje zwoływanie rysowania i nigdy nie dotyka danych pojedynczych cząstek.
Często zadawane pytania
Czy cząstki w grach i filmach symulują rzeczywiste fizyki?
Niecałkowicie. Najczęściej używane są uproszczone kinematyki — grawitacja, opór powietrza, pole turbulencji z curl-noise — zamiast rozwiązywania równań Navier-Stokes, które rządzą rzeczywistym ogniem i dymem. Całkowita dynamika płynów komputerowych jest ograniczona do scen herosowych w filmach, gdzie czas renderowania nie jest ograniczony; gry prawie zawsze używają tańszej przybliżenia, ponieważ muszą działać na 60 klatek na sekundę razem z wszystkim innym na ekranie.
Dlaczego łączenie dodawane sprawia, że ognie i błyski wyglądają jasne i świeże?
Łączenie dodawane dodaje kolor każdego cząsteczka bezpośrednio do piksela już na ekranie zamiast mieszania między nimi, więc przewalające się cząsteczki stackują jasność aż do granic białości. To symuluje zachowanie rzeczywistego ciepła — wiele przelatujących źródeł fotonów naprawdę dodaje się — co sprawia, że wydaje się przekonujące dla ognia i błysków, ale nieprawidłowe dla dymu lub pyłu, które absorbują światło i potrzebują standardowego łączenia przez alfa zamiast tego.
Czym jest curl-noise i dlaczego jest używane do turbulencji zamiast zwykłego szumu?
Curl-noise to szum, który bierze curl pola Perlin noise, tworząc pole wektorowe, które jest konstrukcyjnie bez źródeł ani ujmgów — cząsteczki kręcą się i nigdy nie zbierają ani się rozrastają nieznaturalnie. Adwersja cząsteczek po progresji gradientu Perlin noise zamiast tego może powodować, że tworzą klumpi lub cienkie warstwy, co wygląda obwieszczeniem źle dla dymu i ognia, które powinny zachować objętość podczas krzyżowania się i przemieszczania się.
Wypróbuj na żywo
Wszystko powyżej działa bezpośrednio w Twojej przeglądarce — otwórz Particle VFX i zmieniaj parametry podczas działania. Nic nie jest instalowane ani przesyłane na serwer, cały model działa w jednej karcie.
▶ Otwórz symulację Particle VFX