DIFFUSE · cosine-weightedGGX · naiwne vs VNDFROK · Heitz 2018EXT OF · R.11 · Dodatek B
Dodatek AD / Głębiej: BRDF

Importance sampling dla BRDF

Dodatek B nauczył Cię ogólnej idei importance sampling — próbkuj częściej tam, gdzie wkład i tak jest większy. Ten dodatek stosuje to wprost do kształtu konkretnego loba: jak losować kierunek L tak, żeby prawie każda próbka trafiała tam, gdzie dana BRDF faktycznie coś zwraca, zamiast marnować próbki na kierunki bliskie zeru.

TL;DR
Pass: Diffuse

Cosine-weighted sampling: idealne dopasowanie do Lamberta

Estymator Monte Carlo z Rozdziału 15 dzieli wkład każdej próbki przez jej gęstość prawdopodobieństwa (pdf), z której ją wylosowano. Jeśli wylosujesz kierunek L z gęstością proporcjonalną do samego cosinusa N·L — zamiast równomiernie po całej hemisferze — cosinus w liczniku równania renderowania i cosinus w mianowniku pdf skracają się do zera roboty:

pdf(L) = (N·L) / π   →   f(L,V)·(N·L)/pdf(L) = (kd/π)·(N·L) / ((N·L)/π) = kddla stałej BRDF Lamberta f=kd/π — po skróceniu zostaje sama stała kd, bez cosinusa i bez π w kodzie

Praktyczna konstrukcja (Malley's method): weź dwie liczby losowe ξ₁, ξ₂ ∈ [0,1), rzuć punkt równomiernie na dysk jednostkowy, podnieś go prostopadle na hemisferę:

r = √ξ₁   φ = 2π·ξ₂   L = (r·cos φ, r·sin φ, √(1−ξ₁))L w lokalnym układzie, gdzie oś z pokrywa się z N; trzecia współrzędna √(1−ξ₁) to właśnie N·L tej próbki

Dlaczego rzut na dysk, a nie coś bardziej „bezpośredniego"? Bo równomierny rozkład punktów na dysku, podniesiony prostopadle na hemisferę, automatycznie gęstnieje bliżej bieguna (N·L blisko 1) i rzednie bliżej równika — dokładnie rozkład proporcjonalny do cosinusa, bez żadnej dodatkowej wagi do policzenia.

Pass: GGX naiwnie

Naiwne próbkowanie D(H): gdzie marnujesz próbki

Najprostszy sposób próbkowania GGX z Rozdziału 11: losuj H bezpośrednio z rozkładu D(H), potem odbij V względem H, żeby dostać L. Gęstość prawdopodobieństwa w przestrzeni H to pdf_H(H) = D(H)·(N·H); po przejściu przez operację odbicia (jakobian tej transformacji) gęstość w przestrzeni L wynosi:

pdf(L) = D(H)·(N·H) / (4·(V·H))dzielenie przez 4·(V·H) to jakobian odbicia V względem H — bez niego gęstość byłaby policzona dla złej przestrzeni kierunków

Problem: D(H) opisuje wszystkie mikrofasetki o normalnej H, łącznie z tymi, które są samo-zasłonięte przez sąsiednie fasetki i z kierunku V w ogóle niewidoczne (dokładnie ten człon G z Rozdziału 11, który potem i tak wyzeruje ich wkład). Naiwne próbkowanie losuje z pełnego D(H), nieświadome G — część wylosowanych kierunków to więc próbki „z góry skazane" na wkład bliski zeru, ale i tak kosztujące pełny test przecięcia i ocenę BRDF.

Pass: VNDF

Sampling widocznych fasetek

VNDF (Heitz, 2018) próbkuje nie z D(H), tylko z rozkładu fasetek faktycznie widocznych z kierunku V — czyli D(H) przemnożone przez to, jaka część nich nie jest samo-zasłonięta:

D_V(H) = G1(V) · max(0, V·H) · D(H) / (N·V)G1(V) — ten sam człon geometryczny Smitha z Rozdziału 11; ta wersja rozkładu z definicji nigdy nie generuje fasetki niewidocznej z V
Naive.vs.VNDFwasted samples
NAIWNE D(H) VNDF fioletowe = samo-zasłonięte, wkład ≈ 0 # wszystkie widoczne, żadna zmarnowana
Ta sama liczba próbek — po lewej część ląduje na fasetkach, których G i tak wyzeruje; po prawej żadna.
Ilustracyjnie: ile próbek marnuje naiwne podejście
Bardzo chropowata powierzchnia, patrzona pod ostrym kątem: G1(V) ≈ 0,3 (tylko 30% mikrofasetek widocznych z V, reszta samo-zasłonięta)
Naiwne D(H): z każdych 100 wylosowanych H średnio ~70 trafia w fasetki niewidoczne z V — ich wkład po pomnożeniu przez G jest bliski zeru, próbka „stracona"
VNDF: ta sama liczba próbek, ale wszystkie 100 pochodzą z fasetek, które i tak są widoczne — zero z góry straconych
To ilustracyjne G1(V)=0,3 to skrajny przypadek (bardzo chropowata powierzchnia, płytki kąt) — dla gładkich materiałów i patrzenia na wprost różnica jest dużo mniejsza, bo prawie wszystkie fasetki i tak są widoczne.

VNDF jest droższe do policzenia per próbka (dodatkowa transformacja geometryczna: „ściśnij" kierunek widzenia przez roughness, próbkuj równomiernie na rzucie dysku, „rozciągnij" z powrotem) — ale ponieważ każda próbka faktycznie coś wnosi, tej samej jakości obrazu dochodzisz mniejszą liczbą próbek niż naiwnym D(H). To ten sam bilans koszt-per-próbka kontra liczba-potrzebnych-próbek, co przy sekwencjach niskiej dyskrepancji z Rozdziału 8 i przy denoiserze z Rozdziału 19 — droższy pojedynczy krok, tańszy cały render.

Z praktyki

„GGX sampling" albo „VNDF sampling" jako nazwa techniczna raczej nie pojawia się bezpośrednio w interfejsie DCC — to szczegół implementacyjny silnika, nie parametr artysty. Widzisz jego efekt pośrednio: nowoczesne silniki (Arnold, Cycles, RenderMan) od kilku lat domyślnie używają VNDF, co jest jednym z powodów, dla których identyczna scena z identyczną liczbą próbek renderuje się dziś wyraźniej mniej szumiąco niż w silnikach sprzed ~2018 roku, bez żadnej zmiany ustawień ze strony artysty.

Słowniczek
Cosine-weighted sampling
Losowanie kierunków z gęstością proporcjonalną do N·L — naturalne dla Lamberta.
Malley's method
Konstrukcja próbki cosine-weighted przez rzut punktu z dysku na hemisferę.
Naiwne próbkowanie D(H)
Losowanie normalnej mikrofasetki wprost z rozkładu D, bez uwzględnienia widoczności.
VNDF
Visible Normal Distribution Function — próbkowanie tylko spośród fasetek widocznych z V.
Jakobian odbicia
Czynnik 4·(V·H) przeliczający gęstość z przestrzeni H na przestrzeń L.