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

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.


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.


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.


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.


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.