¿Obtener una textura de un buffer de renderizado en OpenGL?

13

Tengo un renderbuffer (DepthStencil) en un FBO y necesito obtener una textura de él. Parece que no puedo tener una textura DepthComponent y un DepthStencil renderbuffer en el FBO, así que necesito alguna forma de convertir el renderbuffer en una textura DepthComponent después de haber terminado con él para usarlo más adelante en la tubería.

He probado muchas técnicas para obtener el componente de profundidad del buffer de renderizado durante semanas, pero siempre salgo con basura. Todo lo que quiero al final es la misma textura que obtendría de un FBO si no estuviera usando un buffer de renderizado. ¿Alguien puede publicar algunas instrucciones completas o un código que cubra esta operación aparentemente simple?

EDITAR:

Enlace a una versión extraída del código http://dl.dropbox.com/u/9279501/fbo.cs

Screeny del efecto de profundidad de campo + FBO - sin profundidad (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Screeny sin efecto de profundidad de campo + FBO - profundidad trabajando bien http://i.stack.imgur.com/boOm1.jpg

Rushyo
fuente

Respuestas:

2

Alternativamente, puede simplemente pasar de un FBO a otro, como desde un renderbuffer-based a uno basado en textura. Lo hago de esta manera:

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

(En su caso, donde desea profundizar el búfer, puede usar GL_DEPTH_BUFFER_BIT en lugar de GL_COLOR_BUFFER_BIT)

Después de ingresar al buffer de renderizado basado en texturas, puede usar la textura normalmente; pasarlo a sombreadores como uniforme o lo que quieras.

Trevor Powell
fuente
1

No, eso no es posible. Como máximo, puede glReadPixels los datos a la CPU y crear una textura de los mismos, pero eso será engorroso y lento. Los Renderbuffers no son para eso, esa funcionalidad solo es proporcionada por texturas.

Matias Valdenegro
fuente
Dado eso, ¿cuál es la alternativa? ¿Cómo puede mantener la profundidad en su búfer de dibujo y también adquirir el componente de profundidad como textura?
Rushyo
@Rushyo: Una alternativa podría ser deshacerse del búfer de plantilla (si es posible) y hacer que el búfer de renderizado de profundidad tenga una textura de profundidad. ¿Por qué estás usando una plantilla?
Calvin1602
Esencialmente, cada vez que adquiero la textura de profundidad, mis pruebas de profundidad se rompen. Si adjunto un archivo adjunto de profundidad a mi FBO, el FBO no escribe ninguna información de profundidad en otro lugar, por lo que cuando trato de recuperar el archivo adjunto de color no hay pruebas de profundidad (que normalmente es si no tengo un archivo adjunto de profundidad ) He probado todas las combinaciones que se me ocurren, incluido el método "engorroso y lento" mencionado anteriormente. Independientemente de lo que haga, no puedo obtener un render 'típico' de mi escena en una textura y solo la profundidad en otra.
Rushyo
@ Calvin1602 Cuando estaba incursionando con el buffer de renderizado, descubrí que usar el archivo adjunto de profundidad sin el archivo adjunto de plantilla producía resultados no deseados.
Rushyo
@Rushyo Apuesto a que no está configurando la textura correctamente, el código de publicación nos permitirá ayudar :)
Matias Valdenegro
1

Lo que está preguntando es posible en OpenGL 3.2. Tengo mi FBO escupiendo color difuso a una textura de color, normal a otra textura de color y profundidad a una textura de profundidad, no se necesitan buffers de renderizado. De hecho, los renderbuffers son solo un problema, ya que no puede probarlos, por lo que debería usarglReadPixels(...) o copiar de alguna manera los datos del RBO y en una textura en la CPU, en lugar de simplemente mantener todo en la memoria de la GPU. Entonces...

Si realmente lo desea, puede escribir código en su sombreador de primer paso para generar manualmente cosas como profundidad, en un archivo adjunto de textura de color separado en su FBO. Eso sería para que usted lo use en sus sombreadores de postpaso. Para el uso de OpenGL en su prueba de profundidad interna, también necesitará un conjunto de RBO o textura como GL_DEPTH_ATTACHMENT de su FBO. Pero puede configurar una textura única para servir a ambos : esto es más eficiente y más fácil de usar.

Mi código de configuración de textura de profundidad se ve así (Java, simplemente ignore las cosas de ByteBuffer ... y tenga en cuenta que uso "id" para referirme a los controladores / punteros enteros, ya que ese concepto realmente no se siente bien en 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);

Y después:

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

Ahora puede pasar gBufferDepthTexture(o lo que tenga) como uniforme a sus sombreadores de fragmentos de segundo, tercer paso. Creo que podemos suponer con seguridad que puede hacer exactamente lo mismo con el búfer de plantilla.

Ingeniero
fuente
0

Debería poder crear una textura (en lugar de un RenderBuffer) utilizando el formato GL_DEPTH_STENCIL. No estoy seguro del proceso exacto para usar la profundidad de dicha textura en un programa de sombreado (que supongo que estás usando, ya que estás usando FBO), pero la especificación OpenGL debería especificar qué canales de color obtienen qué valores ( Supongo que R, G y B se configuran en profundidad y A se configura en plantilla).

Me dirijo a OpenGL 3.2 en estos días, por lo que es posible que deba verificar que el formato de textura sea viable para usted. Nunca puedo recordar qué versiones presentan diferentes características.

Branan
fuente
El problema no es capturar el componente GL_DEPTH_STENCIL en una textura, sino el hecho de que toda la información de profundidad se pierde en el FBO cada vez que lo hace. El FBO se vuelve inútil para luego representar la escena en el búfer de dibujo. Por lo tanto, estaba usando un Renderbuffer con la esperanza de evitar este problema. Creo que por ahora no tengo más opción que hacer dos pases para obtener la profundidad + extraer información por separado = (caro como el infierno hasta que pueda encontrar una forma de
evitarlo
@Rushyo publiqué una respuesta a esta antigua pregunta :) Es posible que desee echar un vistazo, aunque probablemente lo resolvió hace años.
Ingeniero
¡@NickWiggill lo deseo! Fudged algo y seguí con mi vida. En realidad, no puedo probar su respuesta hasta que vuelva a crear los activos que utilicé en este prototipo. Podría llegar a eso en algún momento ...
Rushyo