2014-04-29 31 views
9

Chcę uzyskać dostęp do wartości bufora głębi w aktualnie przetwarzanym pikselu w cieście pikseli.OpenGL - Jak uzyskać dostęp do wartości bufora głębokości? - Lub: gl_FragCoord.z ​​vs. Renderowanie głębi do tekstury

Jak możemy osiągnąć ten cel? Zasadniczo istnieją dwie opcje:

  1. Głębokość renderowania do tekstury. Jak możemy to zrobić i jaki jest kompromis?
  2. Użyj wartości dostarczonej przez gl_FragCoord.z ​​- Ale: Czy to jest poprawna wartość?
+0

'gl_FragCoord.z' jest wartością głębi aktualnie przetwarzanego fragmentu, a nie aktualną wartością w buforze głębi. Aby uzyskać teksturę głębi, utwórz teksturę z formatem głębi, wyślij do pliku FBO z teksturą głębi dołączoną do pliku GL_DEPTH_ATTACHMENT, a następnie połącz teksturę głębi do próbkowania w module cieniującym fragmentu. –

+0

@RetoKoradi, brzmi jak odpowiedź, dlaczego zrobiłeś komentarz? – JWWalker

+0

@JWWalker: Ponieważ byłem w pośpiechu i zwykle staram się sformułować moje odpowiedzi nieco ostrożniej i bardziej szczegółowo. Zamienię to w odpowiedź. –

Odpowiedz

22

Na pytanie 1: Nie można bezpośrednio odczytać z bufora głębi w module cieniującym fragmentu (chyba że istnieją ostatnie rozszerzenia, które nie są mi znane). Musisz renderować do obiektu bufora ramek (FBO). Typowe kroki:

  1. Utwórz i połącz usługę FBO. Wyszukaj połączenia, takie jak glGenFramebuffers i glBindFramebuffer, jeśli wcześniej nie korzystałeś z FBO.
  2. Utwórz teksturę lub bufor renderowania, który będzie używany jako bufor kolorów, i dołącz go do punktu przyłączenia urządzenia FBO GL_COLOR_ATTACHMENT0 za pomocą glFramebufferTexture2D lub glFramebufferRenderbuffer. Jeśli zależy ci tylko na głębokości od tego przejścia renderowania, możesz pominąć to i renderować bez bufora kolorów.
  3. Utwórz teksturę głębi i dołącz ją do punktu przyłączenia urządzenia FBO do GL_DEPTH_ATTACHMENT.
  4. Wykonaj renderowanie, które tworzy głębokość, z której chcesz korzystać.
  5. Użyj glBindFramebuffer, aby przełączyć się z powrotem do domyślnego bufora ramki.
  6. Powiąż teksturę głębi z próbnikiem używanym przez moduł cieniujący fragmentu.
  7. Twój shader fragmentów może teraz pobierać próbki z tekstury głębi.

Na Pytanie 2: gl_FragCoord.z jest wartość głębi fragment shader, że działa na nie, bieżąca wartość bufora głębokości w miejscu fragmentu.

+1

Załóżmy, że renderuję do bufora ramki o tym samym rozmiarze co moje drugie przejście. Czy tekstura (depth_texture, vec2 (float (gl_FragCoord.x)/width, float (gl_FragCoord.y)/height)) .r index _prawdopodobnie prawą wartość tekstury i odczytać wartość głębokości poprzedniego przejścia? Widzę artefakty "dzwoniące" w pobliżu dużych nieciągłości w buforze głębi. –

+0

Jak przekonwertować wartość głębokości uzyskaną za pomocą wywołania 'texture()' wewnątrz fragmentu shadera z powrotem na "rzeczywiste" współrzędne globalne? Jeśli dobrze rozumiem, wartości głębokości są zaciśnięte na "[0; 1]" - a więc jaką wartością jest pomnożyć zaciśniętą głębokość? – PinkTurtle

+1

Głębokość jest określana za pomocą wartości bliskich i odległych ustawionych w macierzy rzutowania. Po prostu pomnóż różnicę między bliską a daleką i dodaj zbliżoną wartość, aby uzyskać oryginalną wartość ((((daleko - blisko) * Głębokość) + blisko). – MasterPlanMan

5

gl_FragCoord.z to wartość głębi okna dla bieżącego fragmentu. Nie ma nic wspólnego z wartością przechowywaną w buforze głębi. Wartość może być późniejsza zapisana do bufora głębi, jeśli fragment nie jest discard ed i przechodzi test szablon/głębokość.

Technicznie istnieją pewne optymalizacje sprzętu, które wcześnie zapisują/testują głębokość, ale dla wszystkich intencji i celów gl_FragCoord.z nie jest wartością przechowywaną w buforze głębi.

Jeśli nie wykonasz renderowania w wielu przejściach, nie możesz odczytać i zapisać do bufora głębi w module cieniowania fragmentów. Oznacza to, że nie można użyć tekstury głębi do odczytania głębi, a następnie odwrócić i napisać nową głębię. Przypomina to próbę implementacji mieszania w module cieniującym fragmentów, chyba że zrobisz coś egzotycznego ze sprzętem klasy DX11 i ładowaniem/przechowywaniem obrazu, to po prostu nie zadziała.

Jeśli potrzebna jest tylko głębokość końcowej narysowanej sceny dla odwzorowania cienia, można wykonać wstępne przejście tylko do głębokości w celu wypełnienia bufora głębi. W drugim przejściu odczytałeś bufor głębi, ale nie zapisałeś do niego.