Jakie są metody renderowania przezroczystości w OpenGL

14

Mieszanie alfa można włączyć, aby powierzchnie były przezroczyste, na przykład:

glDisable(GL_DEPTH_TEST); //or glDepthMask(GL_FALSE)? depth tests break blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Ale działa to tylko wtedy, gdy obiekty są renderowane w kolejności od początku do końca. W przeciwnym razie rzeczy w tle pojawią się przed bliższymi obiektami, np. Podłoga na obrazku poniżej. W przypadku cząstek i elementów GUI sortowanie byłoby OK, ale w przypadku siatek trójkątów wydaje się, że byłoby to zbyt trudne i wolne, jak omówiono tutaj: https://www.opengl.org/wiki/Transparency_Sorting .

Jakie są typowe metody radzenia sobie z tym? Wiem, że jest to dość szerokie i nie wymagam dogłębnych szczegółów implementacyjnych, tylko krótki opis niektórych podejść i tego, co może być zaangażowane.

wprowadź opis zdjęcia tutaj

jozxyqk
źródło
Nie jestem pewien, czy powinno to być odpowiedzią, czy nie, ale błędy w obrazie są spowodowane renderowaniem bez testowania głębokości na wszystkich elementach podstawowych. Powinieneś renderować scenę w 2 przejściach: Najpierw renderuj normalnie całą geometrię bryłową. Następnie wyłącz zapisywanie głębokości (nie GL_DEPTH_TEST) i renderuj półprzezroczystą geometrię w mniej więcej kolejności. Zapewni to, że przezroczysta geometria nie zostanie narysowana przed geometrią bryłową, która jest przed nią.
yuriks,
@yuriks W tym przypadku jest to prawdopodobnie zły przykład z mojej strony, ale wszystko ma być przejrzyste. Chciałem, żeby coś pokazało, jak źle może wyglądać przezroczystość, gdy zrobione źle. Także przykład, w którym sortowanie geometrii byłoby niezwykle trudne (na przykład tutaj podłoga jest jednym wielkim wielokątem i obejmuje cały zakres głębokości).
jozxyqk

Odpowiedzi:

11

Zestaw technik pozwalających uniknąć jawnego zamawiania jest nazywany „Niezależna przejrzystość zamówień” (w skrócie OIT).

Istnieje wiele technik OIT.

Historycznie jednym z nich jest Peeling Głębokości . W tym podejściu najpierw renderujesz fragmenty / piksele znajdujące się z przodu, a następnie znajdujesz się najbliżej tego, który znaleziono w poprzednim kroku i tak dalej, z taką ilością „warstw”, ile potrzebujesz. Nazywa się to peelingiem głębinowym, ponieważ przy każdym przejściu „obierasz” jedną warstwę głębokości. Całą warstwę można wtedy normalnie połączyć ponownie od tyłu do przodu. Aby wdrożyć ten algorytm, musisz mieć kopię bufora głębokości.

Kolejnym zestawem technik są mieszane OIT. Jednym z najnowszych i interesujących jest Weighted Blended OIT zaproponowany przez McGuire i Bavoil . Zasadniczo stosuje sumę ważoną dla wszystkich powierzchni zajmujących dany fragment. Proponowany przez nich schemat ważenia oparty jest na przestrzeni Z kamery (jako przybliżenie do okluzji) i nieprzezroczystości.
Chodzi o to, że jeśli możesz zredukować problem do ważonej kwoty, tak naprawdę nie zależy ci na zamawianiu.

Oprócz oryginalnego artykułu, na blogu Matta Pettineo znajduje się świetne źródło informacji o szczegółach implementacji i problemach ważonego mieszanego OIT . Jak można przeczytać w jego poście, technika ta nie jest srebrną kulą. Główny problem polega na tym, że schemat ważenia ma kluczowe znaczenie i należy go dostosować do sceny / treści. Z jego eksperymentów, chociaż technika wydaje się działać dobrze w przypadku względnie małego i średniego krycia, nie udaje się, gdy krycie zbliża się do 1, a zatem nie można jej stosować z materiałów, w których duża część powierzchni jest nieprzezroczysta (podaje przykład liści).

Ponownie wszystko sprowadza się do tego, jak dostroić wagi głębokości i znalezienie tych, które idealnie pasują do twoich przypadków użycia, niekoniecznie jest trywialne.

Jeśli chodzi o to, co jest potrzebne do ważonego mieszanego OIT, nic więcej niż dwa dodatkowe cele renderowania. Taki, który wypełniasz wstępnie pomnożonym kolorem alfa (kolor * alfa) i alfa, oba odpowiednio ważone. Drugi tylko dla obciążników.

CIFZ
źródło
6

Jedną z opcji jest użycie peelingu głębokiego.

Zasadniczo jeden przetwarza scenę określoną liczbę razy (powiedzmy nrazy) w celu ustalenia najbliższych, drugich najbliższych, aż do nnajbliższych fragmentów sceny.

Przetwarzanie odbywa się najpierw poprzez zastosowanie regularnego testu głębokości do całej sceny (co naturalnie zwraca najbliższą powierzchnię). Następnie wykorzystuje się wynik testu głębokości, aby odfiltrować pierwszą warstwę, ignorując wszystko z mniejszą głębokością niż zwrócona w teście głębokości.

Ponowne zastosowanie testu głębokości zwróci drugą warstwę. Powtórz w razie potrzeby.

Po utworzeniu warstw możesz po prostu narysować wszystkie warstwy w odwrotnej kolejności (zakładając, że śledziłeś kolory RGBA dla każdej warstwy), mieszając normalnie, ponieważ warstwy są w kolejności od przodu do tyłu.

es1024
źródło
1
Dzięki! Wygląda na to, że potrzebuję do tego dwóch buforów głębokości. Tj. Do przechowywania i filtrowania ostatnich głębokości, a drugi do testowania głębokości dla bieżącego renderowania. Popraw mnie, jeśli się mylę, ale zakładam, że będę potrzebować dwóch tekstur głębokości dla FBO, które zamieniam między każdym przejściem do obierania.
jozxyqk
1
@ jozxyqk Prawidłowo do tej procedury potrzebne są dwa bufory głębokości.
es1024,
1

Creme de la creme jednoprzebiegowego braku (lub kilku) zagraża przejrzystości w OpenGL jest buforem A. Dzięki nowoczesnemu OpenGL możliwe jest wdrożenie:

http://blog.icare3d.org/2010/06/fast-and-accurate-single-pass-buffer.html

Unika wielokrotnych przejść głębokiego obierania i nie wymaga uciążliwego sortowania.

XenonofArcticus
źródło
3
Idealnie byłoby, gdyby odpowiedzi były niezależne i zależały w dużej mierze od linków zewnętrznych. Posiadanie linków jest przydatne w przypadku materiałów uzupełniających, ale odpowiedź nie powinna składać się wyłącznie ze słowa kluczowego. Jeśli możesz podać kilka szczegółów na temat bufora A i jego działania, znacznie poprawiłoby to twoją odpowiedź.
Martin Ender,