Strona głównaArtykułyRenderowanie

Śledzenie Torów: Równanie Renderowania, Monte Carlo i Ruletka Rosyjska

Symulacja losowego odbijania fotonów — zamiast ręcznie kodowanych hacków oświetleniowych — generuje miękkie cienie, barwienie i rażące promieniowanie za darmo.

mysimulator teamZaktualizowano — czerwiec 2026≈ 11 min czytania▶ Otwórz symulację

Jedna całka opisuje cały transport światła

Rasteryzacja – technika stojąca za grami w czasie rzeczywistym – szybko rysuje trójkąty i fałszuje oświetlenie przy użyciu wielu oddzielnych sztuczek: mapy cieni, osłona otoczenia, zbadane promienie świetlne, odbicia przestrzenne ekranu, każda rozwiązująca jeden wąski problem. Path tracing podejmuje zupełnie inny podbój: bezpośrednio analizuje fizyczną równanie, które rządzi ruchem światła przez scenę, po raz pierwszy sformalizowane przez Jamesa Kaji’ego w 1986 roku jako równanie renderowania.

L_o(x, ω_o) = L_e(x, ω_o) + ∫_Ω f_r(x, ω_i→ω_o) · L_i(x, ω_i) · (ω_i · n̂) dω_i L_e = emisja powierzchni f_r = BRDF (jak powierzchnia rozprasza światło) L_i(x, ω_i) = L_o(x', −ω_i) — rekurencyjne: światło padające wejściowe jest światłem wychodzącym w innym miejscu ω_i · n̂ = cos θ_i, współczynnik kosinusa Lambertowskiego; Ω = półkulę powyżej powierzchni Ponieważ L_i po prawej stronie zależy od L_o w jakimś innym punkcie, równanie jest rekurencyjne – rozwijane, stanowi ono nieskończoną sumę wszystkich ścieżek o dowolnej długości: światło bezpośrednie, jeden odbit, dwa odbicia i tak dalej. Każdego efektu wizualnego, który renderer mógłby chcieć – miękkie cienie, wyciek kolorów, kwasowość – już zawiera się w tej jednej całce. Całe wyzwanie path tracingu polega na jej efektywnej oszacowaniu.

L_o(x, ω_o) = L_e(x, ω_o) + ∫_Ω f_r(x, ω_i→ω_o) · L_i(x, ω_i) · (ω_i · n̂) dω_i

L_e = the surface's own emission        f_r = the BRDF (how the surface scatters light)
L_i(x, ω_i) = L_o(x', −ω_i)             — recursive: incoming light IS outgoing light elsewhere
ω_i · n̂ = cos θ_i, the Lambertian cosine term; Ω = the hemisphere above the surface

Szacowanie całki poprzez rzucanie kośćmi

Całka półkulowa nie ma zamkniętej postaci dla dowolnej sceny, więc jest przybliżana przez całkowanie Monte Carlo: narysuj N losowych kierunków, oceń funkcję wyznacznika w każdym z nich i uśrednij.

∫ f(x) dx ≈ (1/N) Σ f(xᵢ) / p(xᵢ) xᵢ wyciągnięte z gęstości prawdopodobieństwa p Obserwowane: E[szacowanie] = prawdziwa całka, dla dowolnego N Odchylenie standardowe ∝ 1/√N → 4x więcej próbek tylko połowę zmniejsza widoczny szum To zbieżność 1/√N jest definiującym ograniczeniem całej dziedziny: dlatego świeżo rozpoczęty renderowany ślad promieniowy wygląda na ziarnisty i powoli się wygładza, oraz dlaczego tak wiele wysiłku badawczego poświęca się albo redukcji wariancji na próbkę (ważne próbkowanie, następny zdarzenie), albo usuwaniu szumów z wyniku zamiast brutalnego zwiększania liczby próbek.

∫ f(x) dx ≈ (1/N) Σ f(xᵢ) / p(xᵢ)      xᵢ drawn from probability density p
Unbiased: E[estimate] = the true integral, for any N
Standard deviation ∝ 1/√N  →  4x more samples only halves the visible noise

BRDF: Jak powierzchnia faktycznie rozprasza światło

Termin BRDF – czyli funkcja rozpraszania rozproszonego (Bidirectional Reflectance Distribution Function) opisuje materiał. Idealnie matowa (Lawembertowska) powierzchnia ma najprostszą możliwą funkcję BRDF, f_r = albedo/π, co oznacza równomierne rozpraszanie światła padającego z każdej strony. Rzeczywiste materiały – np. metal wżynany, tworzywa sztuczne, skóra – zazwyczaj modelowane są przy użyciu funkcji BRDF mikrofacet, takiej jak GGX, która traktuje powierzchnię jako statystyczne pole małych luster i łączy funkcję rozpraszania oparte na normalnej dystrybucji, termin geometrycznego cienia maski oraz współczynnik odbicia Fresnela w jednym fizycznie uzasadnionym łobie odbiciową, która ciągle sięga od ostrych lusterek po miękkie, połyskujące refleksy.

demo na żywo · powiązana symulacja● LIVE

Śledzenie jednej ścieżki z kamery

Rdzeń pętli wystrzeli promień z kamery, odbija go od tego, co uderza w niego, zgodnie z BRDF powierzchni, i gromadzi emitowane światło po drodze, ważone przez bieżącą współczynnik przepuszczalności, który śledzi, ile oryginalnego światła przeżywa każdy odbicie:

tracePath(promień, maxDepth = 8): przepustowość = 1; promieniowanie = 0 for głębokość w 0..maxDepth: uderzenie = scena.przecinaj(promień); jeśli !uderzenie: przerwać promieniowanie += przepustowość * uderzenie.materiał.emisja (wi, pdf, brdfVal) = uderzenie.materiał.próbuj(uderzenie.normalna, promień.kierunek) przepustowość *= brdfVal * cos(uderzenie.normalna, wi) / pdf // BRDF * kosinus / pdf promień = {pochodzenie: uderzenie.punkt, kierunek: wi} zwróć promieniowanie Wybór wi równomiernie w całym półkuli byłby marnowaniem większości próbek na kierunki, które niewiele wnoszą. Ważne próbkowanie zamiast tego rysuje wi z rozkładu ukształtowanego jak całka - dla powierzchni Lambertowskiego, ważone kosinusem próbkowanie półkulowe wybiera kierunki proporcjonalne do cos θ, co wygodnie wyzerowuje kosinusowy termin w aktualizacji przepustowości.

tracePath(ray, maxDepth = 8):
  throughput = 1;  radiance = 0
  for depth in 0..maxDepth:
    hit = scene.intersect(ray);  if !hit: break
    radiance += throughput * hit.material.emission
    (wi, pdf, brdfVal) = hit.material.sample(hit.normal, ray.dir)
    throughput *= brdfVal * cos(hit.normal, wi) / pdf     // BRDF * cosine / pdf
    ray = { origin: hit.point, dir: wi }
  return radiance

Zatrzymanie bez uprzedzenia: rosyjska ruleta

Ograniczanie długości ścieżki promieniowania do stałej głębokości jest proste, ale wprowadza systematyczny błąd – długie ścieżki światła (np. przez szkło do jasnego źródła) są obcinane za każdym razem i ich wkład jest całkowicie tracony. Rosyjska ruleta losowo kończy ścieżkę zamiast tego, z prawdopodobieństwem przeżycia q – często luminansem aktualnej przepływowości – i skaluje wszystkie przetrwałe ścieżki przez 1/q. Ponieważ E[(przepływowość/q) * q] = przepływowość, oszacowanie pozostaje bezstronne, nawet jeśli większość indywidualnych ścieżek jest obcinana, co pozwala rendererowi ograniczyć najgorszy koszt bez systematycznego ciemnienia obrazu.

Frequently asked questions

Dlaczego śledzenie ścieżek generuje szumy w obrazach przy niskiej liczbie próbek?

Śledzenie ścieżek oszacowuje całkę równania renderingu za pomocą losowych próbek Monte Carlo, a odchylenie standardowe tego oszacowania spada proporcjonalnie do 1/√N. Podwojenie liczby próbek na piksel tylko dzieli szumy w połowę, dlatego obraz ostateczny zazwyczaj potrzebuje setek lub tysięcy próbek, chyba że stosowane są metody redukcji szumów lub inteligentne próbkowanie.

Co to jest rosyjska ruletka i dlaczego nie wpływa na wynik?

Rosyjska ruletka losowo kończy ścieżkę światła z prawdopodobieństwem 1−q, a skaluje wskaźnik przyczyniający się do przetrwania przez 1/q. Ponieważ wartość oczekiwana (wkład/q) × q równa się oryginalnemu wkładowi, oszacowanie pozostaje bezstronne średnio, nawet jeśli poszczególne ścieżki są przycinane — co pozwala rendererowi ograniczyć długość ścieżki bez systematycznego ciemnienia obrazu.

Dlaczego śledzenie ścieżek uzyskuje globalne oświetlenie i miękkie cienie za darmo?

Rasteryzacja przybliża oświetlenie oddzielnymi hackami — mapy cieni, osłona otoczenia, wypalane sondy oświetleniowe — dołączonymi indywidualnie. Śledzenie ścieżek zamiast tego bezpośrednio oblicza całkę renderingu, podążając za losowo próbkowanymi ścieżkami światła przez scenę, dzięki czemu pośrednie odbicia, wyciek kolorów i miękkie cienie obszarowe pojawiają się automatycznie z tej samej fizycznej całki, bez specjalnych przypadków kodu dla każdego efektu.

Wypróbuj na żywo

Wszystko powyżej działa bezpośrednio w Twojej przeglądarce — otwórz the simulation 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ę the simulation

Co znalazłeś?

Dodaj kroki odtworzenia (opcjonalnie)