Uzyskiwanie tekstury z bufora renderowania w OpenGL?

13

Mam renderbuffer (DepthStencil) w FBO i muszę uzyskać z niego teksturę. Wygląda na to, że nie mogę mieć zarówno tekstury DepthComponent, jak i bufora renderującego DepthStencil w FBO, więc potrzebuję jakiegoś sposobu, aby przekonwertować bufor renderujący na teksturę DepthComponent po tym, jak skończę z nim do późniejszego wykorzystania w potoku.

Próbowałem wielu technik, aby pobrać komponent głębokości z bufora renderowania od tygodni, ale zawsze wychodzę z śmieciami. Na koniec chcę tylko tej samej tekstury, którą otrzymałbym od FBO, gdybym nie używał bufora renderowania. Czy ktoś może opublikować wyczerpujące instrukcje lub kod, który obejmuje tę pozornie prostą operację?

EDYTOWAĆ:

Linky do wyodrębnionej wersji kodu http://dl.dropbox.com/u/9279501/fbo.cs

Screeny efektu głębi pola + FBO - bez głębi (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Screeny bez efektu głębi pola + FBO - głębia działa dobrze http://i.stack.imgur.com/boOm1.jpg

Rushyo
źródło

Odpowiedzi:

2

Alternatywnie możesz po prostu przeskakiwać z jednego FBO do drugiego, na przykład z bufora renderującego na teksturowany. Robię to w ten sposób:

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderBufferSurface->m_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_textureSurface->m_fbo);
glBlitFramebufferEXT(0, 0, m_renderBufferSurface->m_width, m_renderBufferSurface->m_height, 0, 0, m_textureSurface->m_width, m_textureSurface->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

(W twoim przypadku, gdzie chcesz dogłębnie buforować, możesz użyć GL_DEPTH_BUFFER_BIT zamiast GL_COLOR_BUFFER_BIT)

Po wtopieniu się w renderbuffer oparty na teksturze, możesz następnie użyć tekstury jak zwykle; przekazując go do shaderów jako mundur lub cokolwiek zechcesz.

Trevor Powell
źródło
1

Nie, to niemożliwe. Co najwyżej możesz glReadPixels dane do procesora i utworzyć jego teksturę, ale będzie to uciążliwe i powolne. Bufory renderowania nie są do tego przeznaczone, ta funkcjonalność jest zapewniana tylko przez tekstury.

Matias Valdenegro
źródło
Biorąc to pod uwagę, jaka jest alternatywa? Jak zachować głębokość w buforze rysowania, a także uzyskać składnik głębokości jako teksturę?
Rushyo
@ Rushyo: Alternatywą może być pozbycie się bufora szablonu (jeśli to możliwe!) I uczynienie bufora renderowania głębokości teksturą głębokości. Dlaczego używasz szablonu?
Calvin1602,
Zasadniczo za każdym razem, gdy uzyskuję teksturę głębokości, moje testy głębokości kończą się. Jeśli dołączę załącznik głębokości do mojego FBO, FBO nie zapisuje żadnych informacji o głębokości gdzie indziej - więc kiedy próbuję odzyskać załącznik koloru, nie ma na nim testów głębi (co zwykle jest, jeśli nie mam załącznika głębokości) ). Wypróbowałem każdą kombinację, o której myślę, w tym wspomnianą metodę „niewygodną i powolną”. Cokolwiek robię, nie mogę uzyskać zarówno „typowego” renderowania mojej sceny w jednej fakturze, jak i głębi w drugiej.
Rushyo,
@ Calvin1602 Kiedy bawiłem się buforem renderującym, zauważyłem, że użycie nasadki głębokościowej bez nasadki matrycowej przyniosło niepożądane rezultaty.
Rushyo,
@Rushyo Założę się, że nie ustawiasz poprawnie tekstury, kod pocztowy pozwoli nam pomóc :)
Matias Valdenegro
1

To, o co pytasz, jest możliwe w OpenGL 3.2. Mój FBO wypluwa rozproszony kolor na teksturę koloru, normalny na teksturę innego koloru i głębię na teksturę głębokości - nie są potrzebne bufory renderujące. W rzeczywistości renderbuffery to tylko problem, ponieważ nie można próbkować z nich, więc trzeba będzie użyć glReadPixels(...)lub w inny sposób skopiować dane z RBO do tekstury na procesorze, zamiast po prostu utrzymywać wszystko w pamięci GPU. Więc...

Jeśli naprawdę chcesz, możesz napisać kod w shaderze pierwszego przejścia, aby ręcznie wyprowadzać takie rzeczy, jak głębia, do osobnego załącznika tekstury koloru w FBO. Będzie to do wykorzystania przez ciebie w shaderach po przejściu. Do użytku OpenGL w wewnętrznych testach głębokości dodatkowo potrzebujesz zestawu RBO lub zestawu tekstur jako GL_DEPTH_ATTACHMENT twojego FBO. Ale możesz ustawić jedną teksturę, która będzie obsługiwała obie - jest to bardziej wydajne i łatwiejsze w użyciu.

Mój kod konfiguracji tekstury głębi wygląda tak (Java, po prostu zignoruj ​​rzeczy ByteBuffer ... i zwróć uwagę, że używam „id” w odniesieniu do uchwytów / wskaźników liczb całkowitych, ponieważ ta koncepcja nie jest zbyt dobra w Javie):

        gBufferDepthTexture = new Texture();
        gBufferDepthTexture.id = glGenTextures();
        gBufferDepthTexture.unit = 2;
        gBufferDepthTexture.width = Display.getWidth();
        gBufferDepthTexture.height = Display.getHeight();
        gBufferDepthTexture.bytes = ByteBuffer.allocateDirect(Display.getWidth()*Display.getHeight() * 4);
        glActiveTexture(gBufferDepthTexture.unit + GL_TEXTURE0); //eg. 0 + 33984 = GL_TEXTURE0, while 31 + 33984 = GL_TEXTURE31.
        glBindTexture(GL_TEXTURE_2D, gBufferDepthTexture.id);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gBufferDepthTexture.width, gBufferDepthTexture.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, gBufferDepthTexture.bytes);
        //...GL_UNSIGNED_INT or GL_UNSIGNED_BYTE may work better for you, instead... YMMV.

        //glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

I później:

        glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo.id);
        //your existing glFramebufferTexture2D(...) calls here
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gBufferDepthTexture.id, 0);

Możesz teraz przekazać gBufferDepthTexture(lub co masz) mundur do swoich shaderów fragmentów drugiego, trzeciego przejścia. Myślę, że możemy bezpiecznie założyć, że możesz zrobić dokładnie to samo z buforem wzornika.

Inżynier
źródło
0

Powinieneś być w stanie utworzyć teksturę (zamiast RenderBuffer) przy użyciu formatu GL_DEPTH_STENCIL. Nie jestem pewien dokładnego procesu używania głębokości z takiej tekstury w programie do cieniowania (który, jak zakładam, używasz, ponieważ używasz FBO), ale specyfikacja OpenGL powinna określać, które kanały kolorów uzyskują jakie wartości ( zgaduję, że R, G i B są ustawione na głębokość, a A na szablon).

Obecnie celuję w OpenGL 3.2, więc może być konieczne sprawdzenie, czy format tekstury jest dla ciebie odpowiedni. Nigdy nie pamiętam, które wersje wprowadzają różne funkcje.

Branan
źródło
Problemem nie jest zatem uchwycenie składnika GL_DEPTH_STENCIL w teksturze, ale fakt, że wszystkie informacje o głębokości są tracone w FBO za każdym razem, gdy to robisz. FBO staje się bezużyteczne do renderowania sceny w buforze losowania. Dlatego użyłem Renderbuffera w nadziei na ominięcie tego problemu. Myślę, że na razie nie mam innej opcji, jak tylko zrobić dwa przejścia, by złapać głębokość + osobno narysować informacje = (drogie jak diabli, dopóki nie znajdę sposobu na obejście tego.
Rushyo
@Rushyo Wysłałem odpowiedź na to starożytne pytanie :) Możesz rzucić okiem, choć prawdopodobnie rozwiązałeś to lata temu.
Inżynier
@NickWiggill Chciałbym! Zaszarpałem coś i ruszyłem z życiem. Nie mogę przetestować odpowiedzi, dopóki nie odtworzę zasobów używanych w tym prototypie. Może kiedyś do tego dojdzie ...
Rushyo,