Unikanie walki z z przypadkowymi powierzchniami

26

Podczas renderowania dwóch nakładających się współpłaskich powierzchni powszechnym problemem jest „walka z”, w której renderer nie może zdecydować, która z dwóch powierzchni znajduje się bliżej kamery, dając wizualne artefakty w obszarze nakładania się.

Standardowym rozwiązaniem tego problemu jest nieznaczne przesunięcie powierzchni podczas projektowania modelu. Czy jest jakieś inne rozwiązanie?

znak
źródło
2
Możesz sprawdzić bufory logarytmiczne głębokości. Jest artykuł o Gamasutra
Mydlasty
1
Kiedy mówisz „współplanarny”, masz na myśli „prawie” lub „dokładnie” współplanarny, a jeśli to ostatnie, czy te powierzchnie są kiedykolwiek identycznymi powierzchniami / trójkątami? Sprzęt do renderowania powinien być deterministyczny (zakładając, że nie przesyłasz losowo) dla ostatniego przypadku i nie miałeś walki. Jeśli jest to przypadek nieidentycznych powierzchni, ale dokładnie współpłaszczyznowych, czy możesz zaktualizować model, aby podzielić powierzchnie na zachodzące na siebie i nie nakładające się części?
Simon F
@ SimonF, przez „współplanarny” mam na myśli „dokładnie współplanarny”. Rozwiązanie Soapy działa tylko w przypadku „prawie współpłaszczyznowym”.
Mark,
Czy możesz podać przykład swoich powierzchni? Jedyne, co mogę wymyślić z góry głowy, to zduplikowane trójkąty, jak wspomniałem @ SimonF.
RichieSams,
@RichieSams najczęstszym przypadkiem, o którym mogę myśleć, są kalkomanie, w których nie potrzebujesz dokładnie zduplikowanych trójkątów.
rys

Odpowiedzi:

10

Jeśli powierzchnie są dokładnie współstrugające, twój los zależy od bogów FPU; najprawdopodobniej będziesz walczył z Z. Jeśli trójkąty są identyczne i wykonasz dokładnie taką samą matematykę dla każdego, to zrobisz to same wartości Z dla obu. Ale znowu stanie się tak tylko wtedy, gdy operacje matematyczne będą identyczne dla obu. (Ponieważ zasadniczo operacje FPU nie są przemienne)

Jednym z możliwych rozwiązań jest całkowite niestosowanie bufora Z. Zamiast tego możesz użyć algorytmu malarza . To prawda, że ​​wiąże się to również ze wszystkimi problemami algorytmu malarzy. Ale rozwiązałoby to walkę Z.

W twoim przypadku ekranowych naklejek przestrzeni (SSD), powszechnym rozwiązaniem jest użycie przesunięcia, czyli prostej cienkiej kostki. Zobacz prezentację Warhammer 40k na temat dysków SSD. Lub post Barta Wrońskiego, w którym poruszono inne problemy z naklejkami, ale także linki do kilku innych prezentacji na temat dysków SSD

RichieSams
źródło
5
Ponowne renderowanie tej samej geometrii przy użyciu tych samych transformacji niezawodnie generuje te same wartości głębokości za każdym razem. (Tj. To nie jest siła , to wola ). Dlatego na przykład działa oświetlenie wieloprzebiegowe do przodu.
Nathan Reed,
@NathanReed poprawiony. Dziękuję za wyjaśnienie
RichieSams,
1
Aby uzyskać tę funkcjonalność, musisz użyć niezmiennika kwalifikatora w glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu
Zauważ, że identyczne wyrażenia modułu cieniującego (i dane wejściowe, oczywiście) podczas oceny pozycji wierzchołków mogą nie wystarczyć do uzyskania identycznych wyników, ponieważ niektóre optymalizacje mogą zależeć od reszty modułu cieniującego. GLSL ma słowo kluczowe „niezmiennik”, aby zadeklarować dane wyjściowe modułu cieniującego, które muszą być identycznie ocenione w różnych modułach cieniujących.
Firadeoclus,
2

Oto jak rozwiązałem to w przeszłości:

  1. Narysuj pierwszy obiekt (ten, który powinien pojawić się za drugim obiektem) za pomocą testów głębokości, ale nie pisania głębi
  2. Narysuj drugi obiekt za pomocą testów głębokości i pisania głębi. Nie spowoduje to walki z, ponieważ nie napisaliśmy żadnej głębi w kroku 1.
  3. Narysuj pierwszy obiekt, pisząc tylko w buforze głębi, a nie w buforze kolorów. Dzięki temu bufor głębokości jest aktualny dla wszystkich pikseli pokrywanych przez obiekt 1, ale nie przez obiekt 2.

Uwaga: aby to zadziałało, obiekty muszą być rysowane kolejno.

domyślna
źródło
0

W zależności od renderera możesz sprawić, że powierzchnie będą bardziej „rozmyte”, stosując minimalne przesunięcie na głębokości multisamplingu przy użyciu algorytmu przypominającego szum. Powinno to dać efekt mieszania dla powierzchni znajdujących się w bliskiej odległości. Dla tego, co wiem, ustawienie głębokości dla próbki w module cieniującym fragmenty jest całkiem nowe w OpenGL, a potem tylko jako rozszerzenie.

OpenGL ma PolygonOffset, ale wymaga wcześniejszej wiedzy, że zamierzasz uczynić coś współpłaszczyznowym. Chociaż nie jest to możliwe w przypadku powierzchni w ramach jednego modelu, może dobrze działać na przykład podczas renderowania drogi nałożonej na kawałek terenu.

Andreas
źródło