WEIGHT · spatial×normal×depthPASS · à-trousRISK · fine detailEXT OF · R.19
Dodatek D / Głębiej: Denoising

Mechanika denoisera

Rozdział 19 powiedział „filtr waży sąsiadów po podobieństwie normalnej”. Ten dodatek pokazuje dokładnie, jak liczy się ta waga — i czemu ta sama mechanika, która ratuje krawędzie, czasem zjada futro.

TL;DR
Pass: Wagi

Filtr bilateralny: waga to iloczyn, nie suma

Każdy sąsiad dostaje wagę będącą iloczynem trzech niezależnych czynników Gaussa — musi być blisko w pikselach, mieć podobną normalną i podobną głębię. Wystarczy, że jeden czynnik spadnie do zera, żeby cały iloczyn spadł do zera, niezależnie jak dobre są pozostałe dwa.

w(p,q) = exp(−|p−q|²/2σ_s²) · exp(−|N_p−N_q|²/2σ_n²) · exp(−|D_p−D_q|²/2σ_d²)σ_s, σ_n, σ_d — promienie tolerancji dla pozycji, normalnej i głębi; każdy czynnik osobno z zakresu [0,1]
Bilateral.weight.breakdownproduct of three factors
P A: s=0,757 · n=0,799 · d=0,999 w = 0,604 (wysoka) B: s=0,757 · n=0,040 · d=0,011 w = 0,00034 (odrzucone)
A i B są identycznie blisko w pikselach (spatial=0,757 dla obu) — tylko normalna i głębia decydują, kto trafia do średniej.
Pełny przykład liczbowy — piksel P i dwaj sąsiedzi
P: normalna N_P=(0,1,0), głębia D_P=5,0, kolor C_P=0,9 (zaszumiona próbka). σ_s=3, σ_n=0,3, σ_d=1.
A (ta sama powierzchnia): offset (2,1)px, N_A=(0; 0,98; 0,2), D_A=5,05, C_A=0,8.
B (przez krawędź): offset (2,−1)px — ta sama odległość co A, N_B=(0,7; 0,7; 0), D_B=8,0, C_B=0,1.
Krok po kroku — sąsiad A
spatial: exp(−(2²+1²)/(2·3²)) = exp(−5/18) = 0,7575
normal: |N_P−N_A|²=0,02²+0,2²=0,0404 → exp(−0,0404/(2·0,3²)) = exp(−0,2244) = 0,7990
depth: (5,0−5,05)²=0,0025 → exp(−0,0025/2) = 0,9988
w_A = 0,7575 · 0,7990 · 0,9988 = 0,6044
Krok po kroku — sąsiad B
spatial: identyczne jak A (ta sama odległość w pikselach) = 0,7575
normal: |N_P−N_B|²=0,7²+0,3²=0,58 → exp(−0,58/0,18) = 0,0399
depth: (5,0−8,0)²=9,0 → exp(−9/2) = 0,0111
w_B = 0,7575 · 0,0399 · 0,0111 = 0,000335 — 1800× mniejsza waga niż A
Wynik: odfiltrowany kolor P
Filtr bilateralny: (1·0,9 + 0,6044·0,8 + 0,000335·0,1) / (1+0,6044+0,000335) = 0,862
Zwykły blur (tylko spatial, bez normal/depth): (1·0,9 + 0,7575·0,8 + 0,7575·0,1) / (1+0,7575+0,7575) = 0,629
Prawdziwa wartość na powierzchni P (średnia P i A, bez B) ≈ 0,85. Filtr bilateralny: błąd 0,012. Zwykły blur: błąd 0,221 — 18× większy.
To jest dokładnie „przeciekanie koloru przez krawędź” (color bleeding) — zwykły blur miesza w ciemny kolor z zupełnie innej powierzchni B, bilateralny go prawie całkowicie odrzuca.
Pass: À-trous

Wielorozdzielczość: filtr z dziurami

Mały kernel nie usuwa dużych, „grudkowatych” plam szumu. Wielki kernel jest drogi i ryzykuje rozmycie prawdziwego detalu. SVGF i podobne techniki robią coś pomiędzy: powtarzają ten sam filtr bilateralny kilka razy, każdy raz z coraz większym rozstawem między próbkowanymi pikselami (à-trous — „z dziurami”, sample'ujesz rzadko, ale na dużym obszarze) — usuwając szum wielu częstotliwości za cenę kilku małych przebiegów, nie jednego gigantycznego.

A-trous.passesincreasing step size
PASS 1 · step=1 PASS 2 · step=2 PASS 3 · step=4
Ten sam piksel centralny (większy punkt) — trzy przebiegi, coraz szerszy zasięg, wciąż tylko 9 próbek każdy.
Pass: Granice

Dlaczego denoiser gubi futro i kaustyki

Filtr (klasyczny albo sieć neuronowa) odróżnia „prawdziwy detal” od „szumu” na podstawie koherencji — czy sąsiednie piksele zgadzają się ze sobą. Cienki włos (Rozdział 20) albo ostra kaustyka (Rozdział 16) są z natury wysokoczęstotliwościowe — zmieniają się piksel do piksela tak samo nagle jak szum. Bez dodatkowej informacji (bufor pokrycia sub-pikselowego, osobna maska) filtr nie ma jak ich rozróżnić.

Fine.detail.lossreal feGaussianBlur
WŁOSY: SYGNAŁ WYSOKIEJ CZĘST. PO AGRESYWNYM DENOISINGU
Prawdziwy Gaussian blur (feGaussianBlur) na tych samych krzywych — dziesięć osobnych włosów staje się jedną miękką masą.
Z praktyki

Slidery „Denoise Strength” / „Blend” w Arnoldzie, RenderManie i Blenderze istnieją właśnie po to, żeby dało się oddać kompromis między szumem i utratą detalu w Twoje ręce. Produkcyjne pipeline'y często renderują włosy, sierść i kaustyki jako osobne AOV/passy i stosują do nich słabszy denoising albo żaden — kompozytując je z powrotem po fakcie, żeby beauty pass mógł dostać pełną moc filtra bez zjadania tego, co się liczy najbardziej.

Słowniczek
Filtr bilateralny
Filtr ważący sąsiadów iloczynem kilku niezależnych czynników Gaussa.
À-trous
Wielokrotny przebieg filtra z rosnącym rozstawem próbek między pikselami.
SVGF
Spatiotemporal Variance-Guided Filtering — konkretna, wpływowa technika łącząca à-trous z historią czasową.
Sygnał wysokiej częstotliwości
Detal zmieniający się nagle piksel do piksela — trudny do odróżnienia od szumu.

To zamyka wszystkie cztery dodatki. Rozdziały 1–22 dały Ci pełny szkielet ray tracingu; te cztery dodatki pokazały, co jest pod maską najważniejszych „czarnych skrzynek” z tego szkieletu — materiałów, próbkowania, przyspieszania i czyszczenia obrazu.

Koniec dodatków