Obtendo uma textura de um renderbuffer no OpenGL?


13

Eu tenho um renderbuffer (DepthStencil) em um FBO e preciso obter uma textura dele. Parece que não posso ter uma textura DepthComponent e um depthStencil no FBO, por isso preciso de alguma maneira de converter o bufferbase em uma textura DepthComponent depois de terminar o uso para usá-lo posteriormente no pipeline.

Tentei várias técnicas para pegar o componente de profundidade do renderbuffer por semanas, mas sempre saio com lixo. Tudo o que quero no final é a mesma textura que receberia de um FBO se não estivesse usando um buffer de renderização. Alguém pode postar algumas instruções abrangentes ou código que cubra essa operação aparentemente simples?

EDITAR:

Linky para uma versão extraída do código http://dl.dropbox.com/u/9279501/fbo.cs

Screeny do efeito Profundidade de Campo + FBO - sem profundidade (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Screeny sem efeito de profundidade de campo + FBO - profundidade funcionando bem http://i.stack.imgur.com/boOm1.jpg

Respostas:


2

Como alternativa, você pode escolher entre um FBO e outro, como um baseado em buffer de renderização e outro baseado em textura. Eu faço assim:

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);

(No seu caso, onde você deseja aprofundar o buffer, você pode usar GL_DEPTH_BUFFER_BIT em vez de GL_COLOR_BUFFER_BIT)

Após selecionar o buffer de renderização baseado em textura, você poderá usar a textura normalmente; passando para shaders como uniforme ou o que você quiser.


1

Não, isso não é possível. No máximo, você pode glReadPixels os dados para a CPU e criar uma textura deles, mas isso será complicado e lento. Renderbuffers não são para isso, essa funcionalidade é fornecida apenas por texturas.


Dado isso, qual é a alternativa? Como você pode manter a profundidade em seu buffer de desenho e também adquirir o componente de profundidade como uma textura?
Rushyo 23/08/10

@Rushyo: Uma alternativa seria livrar-se do buffer de estêncil (se possível!) E tornar a profundidade do buffer de renderização uma textura de profundidade. Por que você está usando um estêncil?
Calvin1602 23/08

Essencialmente, sempre que adquiro a textura de profundidade, meus testes de profundidade são interrompidos. Se eu anexar um anexo de profundidade ao meu FBO, o FBO não gravará nenhuma informação de profundidade em outro lugar - então, quando eu tento recuperar o anexo colorido, não há nenhum teste de profundidade nele (o que normalmente acontece se eu não tiver um anexo de profundidade) ) Eu tentei todas as combinações em que consigo pensar, incluindo o método 'pesado e lento' mencionado acima. O que quer que eu faça, não consigo obter uma representação 'típica' da minha cena em uma textura e apenas a profundidade em outra.
Rushyo 23/08/10

@ Calvin1602 Quando brincava com o renderbuffer, descobri que usar o acessório de profundidade sem o acessório de estêncil produzia resultados indesejados.
Rushyo 23/08/10

@Rushyo Aposto que você não está configurando a textura corretamente, postando código nos permitirá ajuda :)
Matias Valdenegro

1

O que você está perguntando é possível no OpenGL 3.2. Eu tenho meu FBO exibindo cores difusas em uma textura de cor, normais em outra textura de cor e profundidade em uma textura de profundidade - não são necessários amortecedores de renderização. De fato, os buffers de renderização são apenas um problema, porque você não pode obter amostras deles; portanto, você teria que usar glReadPixels(...)ou copiar de alguma forma os dados da RBO para uma textura na CPU, em vez de apenas manter tudo na memória da GPU. Então...

Se você realmente quiser, pode escrever um código no seu sombreador de primeira passagem para enviar manualmente coisas como profundidade, para um anexo de textura de cor separado no seu FBO. Isso seria para você usar em seus shaders pós-passe. Para o uso do OpenGL em seus testes internos de profundidade, você precisaria adicionalmente de uma RBO ou textura definida como GL_DEPTH_ATTACHMENT do seu FBO. Mas você pode configurar uma única textura para servir a ambos - isso é mais eficiente e fácil de usar.

Meu código de configuração de textura de profundidade se parece com isso (Java, apenas ignore o material ByteBuffer ... e observe que eu uso "id" para me referir a identificadores / ponteiros inteiros, já que esse conceito realmente não se encaixa bem em Java):

        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);

E depois:

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

Agora você pode passar gBufferDepthTexture(ou o que você tem) como um uniforme para o seu segundo e terceiro pass shaders de fragmento. Acho que podemos assumir com segurança que você pode fazer exatamente a mesma coisa com o buffer de estêncil.


0

Você deve conseguir criar uma textura (em vez de um RenderBuffer) usando o formato GL_DEPTH_STENCIL. Não tenho certeza do processo exato para usar a profundidade de tal textura em um programa de sombreador (que suponho que você esteja usando, já que usa FBOs), mas a especificação do OpenGL deve especificar quais canais de cores obtêm quais valores ( meu palpite seria que R, G e B são todos ajustados à profundidade e A é definido como estêncil).

Atualmente, tenho como alvo o OpenGL 3.2, portanto, talvez seja necessário verificar se o formato da textura é viável para você. Nunca me lembro quais versões introduzem recursos diferentes.


O problema não é capturar o componente GL_DEPTH_STENCIL em uma textura, mas o fato de que todas as informações detalhadas são perdidas no FBO sempre que você o faz. O FBO se torna inútil para renderizar a cena no buffer de desenho. Portanto, eu estava usando um Renderbuffer na esperança de contornar esse problema. Acho que por enquanto não tenho opção, a não ser fazer dois passes para agarrar a profundidade + desenhar informações separadamente = (caro como o inferno, até que eu possa encontrar uma maneira de contornar isso.
#

@Rushyo Eu postei uma resposta para esta pergunta antiga :) Você pode querer dar uma olhada, embora provavelmente tenha resolvido isso anos atrás.
Engenheiro de

@NickWiggill Desejo! Fudi com alguma coisa e segui em frente com minha vida. Na verdade, não posso testar sua resposta até recriar os ativos que usei neste protótipo. Pode chegar a cerca de que em algum momento ...
Rushyo
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.