MFP · 1/σ_tARNOLD · subsurface_radius × subsurface_scaleRENDERMAN · diffuseMeanFreePath / unitLength
Rozdział 16 / Shading produkcyjny

Subsurface scattering w praktyce

Dodatek AG w poprzedniej książce pokazał, czym jest random walk. Tu jest pytanie, które zadaje każdy artysta: jaki promień MFP wpisać, żeby wosk nie wyglądał jak plastik.

TL;DR
Etap: Fizyka

Ta sama wielkość fizyczna, dwa imiona

Dodatek AG w raytracing-book wyprowadza random walk fotonu pod powierzchnią od podstaw: współczynnik rozpraszania σ_s, współczynnik absorpcji σ_a i ich sumę, współczynnik ekstynkcji σ_t = σ_s + σ_a — im większy σ_t, tym gęstszy ośrodek i tym częściej foton zmienia kierunek. Odwrotność tej sumy to dokładnie ta wielkość, którą oba renderery wystawiają artyście jako suwak:

MFP = 1 / σ_tMFP — mean free path (średnia droga swobodna), przeciętny dystans między dwoma kolejnymi zdarzeniami rozproszenia; σ_t — współczynnik ekstynkcji ośrodka, suma rozpraszania i absorpcji
↓ raytracing-book, Dodatek AG — pełne wyprowadzenie: σ_t, albedo, random walk

MFP jest zawsze podawany per kanał — R, G i B mają różne wartości, bo tkanka (czy dowolny inny ośrodek rozpraszający) pochłania poszczególne długości fali z różną siłą. W skórze hemoglobina i melanina pochłaniają zielone i niebieskie fotony znacznie szybciej niż czerwone, więc czerwone światło przenika głębiej i wraca dalej od punktu wejścia, zanim je zaabsorbuje ośrodek — to właśnie ten efekt widać jako czerwonawą poświatę na uszach czy palcach pod silnym podświetleniem (rim light). Skoro promień/MFP to bezpośrednio odwrotność σ_t, wyższa wartość zawsze oznacza mniej gęsty, bardziej przenikliwy ośrodek — niższa wartość gęstszy, bardziej nieprzezroczysty.

↓ raytracing-book, Dodatek AO — dlaczego hemoglobina i melanina akurat te długości fal pochłaniają
Etap: Arnold

subsurface_radius i pułapka subsurface_scale

aiStandardSurface (Rozdział 13) wystawia SSS jako osobną warstwę shadera, mieszaną z Lambertem, z sześcioma parametrami, które warto umieć czytać wprost jako wielkości fizyczne, a nie jako abstrakcyjne suwaki:

ParametrZnaczenieDomyślnie
subsurfaceWaga: 0 = czysty Lambert, 1 = czysty SSS.0
subsurface_colorAlbedo pojedynczego rozproszenia — barwa/jasność bazowa, osobna od promienia.—
subsurface_radiusMFP per kanał RGB — dystans, na jaki światło rozprasza się pod powierzchnią, zanim wróci na zewnątrz.(1; 1; 1)
subsurface_scaleMnożnik promienia — tu jest schowana konwersja jednostek sceny na rzeczywiste centymetry/milimetry.1
subsurface_typediffusion (tania aproksymacja dipolowa) / randomwalk (prawdziwy random walk, poprawny przy cienkiej geometrii i wklęsłościach) / randomwalk_v2 (dokładniejsza saturacja barwy dla obiektów mocno przezroczystych, kosztowniejszy).randomwalk
subsurface_anisotropyWspółczynnik Henyeya-Greensteina g (−1…1); działa tylko z randomwalk/randomwalk_v2.0

Parametry aiStandardSurface, gałąź Subsurface. Domyślny subsurface_type to randomwalk — dokładniejszy odpowiednik random walk z Dodatku AG, w przeciwieństwie do starszej aproksymacji dyfuzyjnej.

Kluczowy szczegół: subsurface_radius sam w sobie nie mówi nic o rzeczywistej odległości — to subsurface_scale decyduje, czym jest jedna jednostka promienia w danej scenie. Dokumentacja Arnolda podaje wprost: przy scenie zbudowanej w metrach, subsurface_scale = 0,01 sprawia, że liczby wpisane w subsurface_radius zaczynają oznaczać centymetry.

Policzone: subsurface_radius skóry w scenie zbudowanej w metrach
Cel fizyczny — chcemy, by promień R·G·B wynosił 0,37 cm · 0,14 cm · 0,07 cm
Scena — 1 jednostka sceny = 1 m → subsurface_scale = 0,01 (jednostka promienia zaczyna znaczyć 1 cm)
subsurface_radius = (0,37; 0,14; 0,07) — wpisane wprost, bo scale już przeliczył jednostki
Rzeczywisty promień = subsurface_radius · subsurface_scale = 0,37 cm, 0,14 cm, 0,07 cm
To niemal dokładnie te same liczby fizyczne, co zmierzona wartość diffuseMeanFreePath dla materiału „Skin1” w tabeli RenderMana niżej: 3,67 mm / 1,37 mm / 0,68 mm.
Sprawdzenie: 0,37 cm = 3,7 mm ≈ 3,67 mm; 0,14 cm = 1,4 mm ≈ 1,37 mm; 0,07 cm = 0,7 mm ≈ 0,68 mm — zgodność w granicach zaokrągleń, bo to ta sama wielkość fizyczna, tylko inaczej sparametryzowana w dwóch silnikach.
Etap: RenderMan

diffuseMeanFreePath i unitLength

PxrSurface (i PxrLayerSurface, Rozdział 13) nazywa tę samą wielkość dosłownie: diffuseMeanFreePath (w skrócie dmfp) to kolor per kanał, podawany w milimetrach i skalowany globalną własnością unitLength sceny — jednym przelicznikiem dla całego shadera, zamiast osobnego mnożnika przy każdym parametrze.

ParametrZnaczenieJednostka / skalowanie
diffuseMeanFreePathDosłowna średnia droga swobodna fotonu, per kanał RGB.mm, skalowane przez unitLength sceny
subsurfaceColorAlbedo pojedynczego rozproszenia — jasność bazowa, w parze z dmfp.bezwymiarowe, 0–1
model rozpraszaniaJensen Dipole / d'Eon Better Dipole / Burley Normalized (tanie aproksymacje) / Multiple Mean Free Paths / Path Traced (dokładny random walk, odpowiednik Arnoldowego randomwalk).—

Parametry PxrSurface, gałąź Subsurface. Model Path Traced jest kosztowniejszy i bardziej szumiący niż warianty dipolowe — dokładnie ten sam kompromis co Arnoldowy randomwalk kontra diffusion.

Zamiast zgadywać wartości dmfp, warto zacząć od zmierzonych danych referencyjnych — klasyczny zestaw z pracy Jensena i in. o transporcie światła podpowierzchniowego podaje albedo i dmfp dla kilku realnych materiałów:

MateriałAlbedo (R · G · B)dmfp mm (R · G · B)
Skóra (Skin1)0,436 · 0,227 · 0,1313,67 · 1,37 · 0,68
Mleko pełnotłuste0,908 · 0,881 · 0,75910,90 · 6,58 · 2,51
Marmur0,830 · 0,791 · 0,7538,51 · 5,57 · 3,95
Jabłko0,846 · 0,841 · 0,5286,96 · 6,40 · 1,90

Zmierzone wartości referencyjne (Jensen i in., „A Practical Model for Subsurface Light Transport”). Punkt startowy do dalszego strojenia, nie gotowy wynik — geometria, oświetlenie i skala kamery zawsze wymagają korekty.

Radius.per.channelprofil rozpraszania skóry (Skin1): R przenika głębiej niż B
0 2 4 6 8 mm względna intensywność rozproszonego światła R — dmfp 3,67 mm G — dmfp 1,37 mm B — dmfp 0,68 mm
Krzywe zaniku intensywności rozproszonego światła w funkcji odległości od punktu wejścia, dla mierzonych wartości dmfp skóry z tabeli wyżej. Im większy MFP, tym wolniejszy zanik i tym dalej sięga kanał.
Etap: Porównanie

Dwa silniki, jedna wielkość fizyczna

Zestawione obok siebie, oba systemy parametrów mówią dokładnie to samo — różnią się tylko tym, gdzie chowają konwersję jednostek sceny:

PojęcieArnold (aiStandardSurface)RenderMan (PxrSurface)
MFP per kanałsubsurface_radiusdiffuseMeanFreePath (dmfp)
Konwersja jednostek scenyosobny mnożnik subsurface_scaleglobalna własność unitLength
Albedo pojedynczego rozproszeniasubsurface_colorsubsurfaceColor
Dokładny model transportusubsurface_type = randomwalkmodel Path Traced

Ten sam artykuł Jensena i in., z tej samej mierzonej próbki skóry, nadaje się jako punkt startowy w obu silnikach — trzeba tylko wiedzieć, gdzie w każdym z nich wpisać przelicznik jednostek.

Etap: Najczęstszy błąd

Pułapka skali: dlaczego wosk zamiast plastiku

Najczęstszy błąd przy strojeniu SSS nie jest artystyczny — to pomyłka w jednostkach, ukryta za osobnym mnożnikiem (subsurface_scale) albo globalną własnością sceny (unitLength), o której łatwo zapomnieć, przenosząc wartości między silnikami albo między scenami w innej skali.

Policzone: te same liczby dmfp, zapomniany scale
Artysta przepisuje subsurface_radius = (3,67; 1,37; 0,68) wprost z tabeli dmfp RenderMana (wartości w mm)
Scena w Arnoldzie zbudowana w metrach, subsurface_scale pozostawiony na domyślnym 1 — bez przeliczenia
Rzeczywisty promień = subsurface_radius · subsurface_scale = 3,67 · 1 = 3,67 metra (kanał R)
Promień 3,67 metra na twarzy szerokiej na ~15 cm: światło „przenika” praktycznie przez całą głowę, zanim wróci na powierzchnię. Lokalny kontrast znika, forma się rozmywa — efekt wygląda jak przezroczysty wosk albo mydło, nie jak skóra.
Poprawka: subsurface_scale = 0,001 (żeby liczby wpisane w mm faktycznie znaczyły milimetry w metrowej scenie) → rzeczywisty promień wraca do 3,67 mm, w realistycznym zakresie.

Odwrotny błąd daje odwrotny efekt: promień, który w rzeczywistości wychodzi dziesięć razy za mały (np. mikrony zamiast milimetrów), sprawia, że SSS praktycznie się wyłącza — powierzchnia przestaje przepuszczać jakiekolwiek światło pod sobą i wygląda płasko, matowo, jak pomalowany plastik, dokładnie odwrotnie niż wosk. Oba objawy to ten sam błąd o przeciwnym znaku: promień/MFP przestał odpowiadać realnej skali obiektu. Najbezpieczniejsza obrona to zawsze zacząć od zmierzonej wartości referencyjnej (jak tabela Jensena wyżej) i świadomie przeliczyć ją przez scale/unitLength danej sceny — nie od suwaka na oko.

Słowniczek
MFP (mean free path, średnia droga swobodna)
Przeciętny dystans, jaki foton pokonuje pod powierzchnią między kolejnymi zdarzeniami rozproszenia. MFP = 1/σ_t.
σ_t (współczynnik ekstynkcji)
Suma współczynnika rozpraszania σ_s i absorpcji σ_a — im większy, tym gęstszy, mniej przenikliwy ośrodek (raytracing-book, Dodatek AG).
subsurface_radius (Arnold)
MFP per kanał RGB, w jednostkach zależnych od subsurface_scale.
subsurface_scale (Arnold)
Mnożnik promienia — konwertuje jednostki sceny na rzeczywiste centymetry/milimetry.
diffuseMeanFreePath / dmfp (RenderMan)
MFP per kanał RGB w PxrSurface, podawane w mm, skalowane przez unitLength sceny.
Albedo pojedynczego rozproszenia
Jasność/barwa bazowa rozpraszania, osobna od promienia — subsurface_color w Arnoldzie, subsurfaceColor w RenderManie.
randomwalk / Path Traced
Dokładne modele transportu światła pod powierzchnią (prawdziwy random walk), w opozycji do tańszych aproksymacji dipolowych.