SPLIT · SAH-optimalCOST · C_trav + P·N·C_isectGPU · LBVHEXT OF · R.13
Dodatek C / Głębiej: Wydajność

Budowa BVH: SAH i alternatywy

Rozdział 13 pokazał, jak BVH przycina drzewo trawersowania. Nie pokazał, jak zbudować dobre drzewo w pierwszej kolejności — a od tego zależy, czy przycinanie faktycznie coś da.

TL;DR
Pass: Problem

Dlaczego podział na pół nie wystarcza

Najprostsza strategia — podziel obiekty na dwie równe grupy po liczbie, wzdłuż najdłuższej osi — działa świetnie, gdy obiekty są rozłożone równomiernie. Zawodzi, gdy nie są: gęsty klaster małych obiektów w jednym rogu i jeden odległy, duży obiekt gdzie indziej wciąż podzieli się „po połowie”, produkując dwa ogromne, mocno nakładające się pudełka — a przycinanie z Rozdziału 13 działa tylko wtedy, gdy pudełka faktycznie się rozchodzą w przestrzeni.

Median.vs.spatial.splitoverlap matters
PODZIAŁ PO LICZBIE (ŚLEPY) PODZIAŁ ŚWIADOMY PRZESTRZENI pudełka ogromne, nakładają się pudełka szczelne, rozłączne
Te same dziewięć obiektów — po lewej podział „po liczbie” psuje wszystko, po prawej podział rozumie przestrzeń.
Pass: SAH

Surface Area Heuristic: licz koszt, nie zgaduj

SAH formalizuje „jak dobry jest ten podział”, szacując oczekiwany koszt trawersowania — prawdopodobieństwo, że promień wejdzie w każde dziecko, przybliżone stosunkiem powierzchni jego pudełka do powierzchni pudełka rodzica:

koszt(podział) = C_trav + (SA_L/SA_parent)·N_L·C_isect + (SA_R/SA_parent)·N_R·C_isectSA — powierzchnia pudełka (surface area); N — liczba obiektów w dziecku; C_trav, C_isect — koszty jednostkowe trawersowania i testu przecięcia

Budowa drzewa próbuje wielu kandydatów na podział (zwykle wzdłuż każdej osi, w kilkunastu pozycjach) i wybiera ten o najniższym koszcie SAH — rekurencyjnie, dla każdego węzła.

SAH.cost.landscapeminimum wins
kandydaci na pozycję podziału wzdłuż osi wybrany podział
Dolina kosztu — nie zawsze pośrodku, nie zawsze intuicyjna, ale policzona, nie odgadnięta.
Pełny przykład liczbowy — te same 4 obiekty co w poprzednim diagramie
Dane: 4 jednostkowe kostki (1×1×1) wzdłuż osi X: obj1 x∈[0,1], obj2 x∈[2,3], obj3 x∈[4,5], obj4 x∈[10,11] (odległy outlier). C_trav=1, C_isect=1 (jednostki umowne).
Pudełko rodzica: x∈[0,11], y,z∈[0,1]. SA_parent = 2·(11·1+11·1+1·1) = 2·23 = 46
Kandydat 1 — podział „po liczbie” (x=3,5): {obj1,obj2} | {obj3,obj4}
SA_L = pudełko x∈[0,3]: 2·(3+3+1) = 14. N_L=2.
SA_R = pudełko x∈[4,11]: 2·(7+7+1) = 30. N_R=2.
koszt = 1 + (14/46)·2 + (30/46)·2 = 1 + 0,6087 + 1,3043 = 2,9130
Kandydat 2 — podział izolujący outlier (x=6): {obj1,obj2,obj3} | {obj4}
SA_L = pudełko x∈[0,5]: 2·(5+5+1) = 22. N_L=3.
SA_R = pudełko x∈[10,11]: 2·(1+1+1) = 6. N_R=1.
koszt = 1 + (22/46)·3 + (6/46)·1 = 1 + 1,4348 + 0,1304 = 2,5652
Kandydat 2 wygrywa (2,565 < 2,913) — mimo że dzieli obiekty bardziej „nierówno” (3 kontra 1, nie 2 kontra 2).
Sprawdzenie sensu: brak podziału (jeden węzeł, testuj wszystkie 4) kosztowałby 4·C_isect=4,0 — oba kandydaci są lepsi niż brak podziału, a Kandydat 2 jest lepszy od Kandydata 1 właśnie dlatego, że odizolowanie odległego obiektu daje dużo mniejsze, szczelniejsze pudełko SA_R=6, nie 30.
Pass: Alternatywy

LBVH i spatial splits

LBVH (Linear BVH) pomija kosztowną, rekurencyjną ocenę SAH: sortuje obiekty według ich pozycji na krzywej Mortona (Z-order — bity x, y, z przeplecione w jedną liczbę) i budowa drzewa staje się prostym sortowaniem, świetnie równoległym na GPU. Jakość drzewa jest nieco niższa niż z SAH, ale budowa jest na tyle szybka, że opłaca się przebudowywać je co klatkę dla animowanej geometrii.

Spatial splits (SBVH) rozwiązują inny problem: gdy jeden obiekt jest bardzo długi (ściana przez całą scenę), żaden podział po liczbie obiektów nie pomoże — ten jeden obiekt i tak trafi do obu dzieci. SBVH pozwala przeciąć pudełko obiektu w przestrzeni, przypisując różne jego fragmenty do różnych dzieci.

LBVH.morton+ spatial split
LBVH: KRZYWA MORTONA SPATIAL SPLIT (SBVH) fragment L fragment R
Z-order odwiedza sąsiadów w przestrzeni po kolei — idealne do sortowania. Po prawej: jeden długi obiekt, przecięty na dwa fragmenty.
Z praktyki

To dlaczego „Build Acceleration Structure” trwa zauważalnie dłużej dla scen z milionami trójkątów w Arnoldzie czy RenderManie — wysokiej jakości SAH build jest kosztowny, ale opłaca się przy renderze trwającym godziny. Sprzętowy RT (RTX) w grach używa szybszych, LBVH-podobnych buildów z refittingiem co klatkę — bo scena i tak zmienia się 60 razy na sekundę, więc idealne drzewo nie ma czasu się przydać.

Słowniczek
Median split
Podział po liczbie obiektów, niezależnie od ich rozmieszczenia w przestrzeni.
Surface Area Heuristic (SAH)
Szacowanie kosztu podziału przez stosunek powierzchni pudełek.
Koszt trawersowania
Oczekiwana liczba operacji potrzebna do przejścia drzewa dla promienia.
LBVH
Szybka budowa BVH przez sortowanie po krzywej Mortona.
Kod Mortona (Z-order)
Przeplot bitów współrzędnych, dający jednowymiarowe uporządkowanie punktów 3D.
Spatial split (SBVH)
Przecinanie pudełka obiektu między dzieci, nie tylko grupowanie całych obiektów.