Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





P-buffers Con Rtt

Iniciado por MA]Mestre, 24 de Abril de 2005, 04:57:16 PM

« anterior - próximo »

tamat

 Llevo toda la tarde haciendo pruebas y más o menos me aclaro pero tengo algunas dudas:

Estoy intentando hacer que toda la escena se renderice en una textura para despues pintar esa textura en un quad sobre todo el viewport y así poder hacer efectos de desenfoque y demás.
El problema es que si apunto desde mi FBO a una textura, pinto la escena, y despues redirijo el colorbuffer de mi FBO al renderbuffer de la pantalla y pinto el quad me temo que la escena tendrá una resolución horrorosa ya que la textura no creo que mida 1024x768 (además de que no es multiplo de 2).

Por otra parte ahora simplemente hago pruebas con un FBO que lo envia todo a renderbuffers, pero al crearlos me pide un tamaño y por lo que vea tanto da lo que ponga, siempre se ve igual la escena.

 // create the frame object
 glGenFramebuffersEXT(1, &mFramebufferName);

 // create and set the color buffer
 glGenRenderbuffersEXT(1, &mColorBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mColorBufferName);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_RGBA,width,height);

 //create and set the depth buffer
 glGenRenderbuffersEXT(1, &mDepthBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mDepthBufferName);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthBufferName);

 //create stencil
 glGenRenderbuffersEXT(1, &mStencilBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mStencilBufferName);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mStencilBufferName);

 //check everything is perfect
 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 if (status == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
 {
  std::cout << "Extension problem: FBO not completed" << std::endl;  
 }


Para qué es el tamaño que se le pasa al renderbuffer?
Por un stratos menos tenso

DraKKaR

 No veo nada claro ese código:

En ningún momento veo que le digas a OpenGL cual es el buffer de color que tiene que usar (con un glFramebufferRenderbufferEXT, al igual que has hecho con el depth y stencil). Por lo tanto tu FBO no tiene buffer de color asociado.

No estableces el tamaño para todos los renderbuffers, solo para el colorbuffer (que no attacheas)

¿Como compruebas el resultado del RTT? Supongo que con un ReadPixels o similar puesto que un renderbuffer no puedes usarlo como textura, ni blitearlo sobre la pantalla. Mi teoría es que no estas enviando los pixels resultantes donde tu crees y por lo tanto no le afecta ese tamaño que le pasas al colorbuffer (pq realmente no se utiliza!). Y al hacer le ReadPixels o lo que sea estas cogiendo los pixels de ese mismo sitio mágico (el color buffer principal por defecto?) y por eso no ves que cambie nada al variar el tamaño.


Por otra parte, no hay problema al utilizar texturas que no sean potencia de 2. Comprueba que el driver soporta alguna de estas 2 extensiones:
- ARB_texture_non_power_of_two
- ARB_texture_rectangle

Y usa el tamaño que quieras para las texturas.

Por cierto, si no tienes  ningun problema utilizando un FBO con color + depth + stencil avisa ;)

tamat

 Antes hacía dos cosas mal, la primera era no bindear el frameobject y la otra era no poner la linea de glFramebufferRenderbufferXT.

 glGenRenderbuffersEXT(1, &mColorBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mColorBufferName);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_RGBA,width,height);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mColorBufferName); // olvidé esta linea


Pero ahora sigo sin ver nada si activo el frameobject que he creado.
Drakkar, dices que un renderbuffer no se puede enviar a la pantalla? eso me ha parecido entender por lo que dices de blittearlo.
Arg, empiezo a estar algo desesperado. Si alguna persona paciente me quiere agregar al msn o al gmail para ver qué hago mal se lo agradeceré. tamatito en hotmail y javi.agenjo en gmail
Por un stratos menos tenso

DraKKaR

 
CitarDrakkar, dices que un renderbuffer no se puede enviar a la pantalla? eso me ha parecido entender por lo que dices de blittearlo.
Exacto. Esto es así porque el API no permite especificar diferentes FBO de source y FBO de destino por separado para hacer opraciones entre ellos (como hacer un volcado). Para esto mismo existe una extension 'EXT_framebuffer_blit' pero creo que aun no es utilizable (al menos hace unos meses no lo era, no he vuelto a problarlo (si descubres que sí, avisa ;))). Esta extensión permite literalmente "This allows copying directly from one framebuffer to another".

Por eso te decía que no se como compruebas el contenido del renderbuffer. Necesitarias hacer un readpixels, cambiar al FBO normal y hacer un drawpixels o crear una textura con esos pixeles para comprobar su contenido.

Tu piensa que un renderbuffer sirve de contenedor de datos de render, que si bien no los quieres usar como tal, es necesario almacenarlos para renderizar correctamente la escena. Por ejemplo, el depth buffer se suele configurar como renderbuffer y no como texture2d porque lo que tu quieres al final no es el contenido del depth buffer, sino la imagen final. Pero es necesario almacenar en algun sitio el depth buffer para que se renderice correctamente la escena. El color buffer en este caso es el que deberia configurarse como texture 2D porque es lo que buscas utilizar.

Por otra parte, en el caso de hacer shadow mapping, lo que tu quieres es precisamente es contenido del depth buffer. Por lo tanto en este caso configurarias un FBO con una texture 2D como depth attachment y ningún buffer como color attachment. Ya que solo nos interesa el contenido del buffer de profundidad.

¿Me explico?

CitarArg, empiezo a estar algo desesperado. Si alguna persona paciente me quiere agregar al msn o al gmail para ver qué hago mal se lo agradeceré. tamatito en hotmail y javi.agenjo en gmail

Prefiero hablar por aquí, así esto puede servirle a más gente con tu problema, ademas de mi limitada disponibilidad para el MSN.

tamat

 Entonces lo he entendido todo mal. Yo pensaba que los renderbuffers siempre iban a parar a la pantalla, que esa era la diferencia con las texturas. Si lo quieres guardar como textura entonces enganchas al framebuffer una textura, si lo quieres mostrar en pantalla entonces asocias un renderbuffer.
Pero ahora segun lo que dices entiendo que el unico que se puede mostrar en pantalla es el 0, los demás van destinados a usar texturas. Pero no me cuadra qué pintan los renderbuffers.

Por cierto, me acabo de dar cuenta de que mi framebuffer no generaba un estado de completeness, así que al menos tengo algo con lo que trabajar.

Ah, y yo no quiero hacer shadormapping, yo quiero renderizar toda la escena en una textura, a poder ser en cada frame (aunque si es muy costoso pues lo haría cada N frames).

Gracias drakkar por tomarte las molestias
Por un stratos menos tenso

DraKKaR

 
CitarPero ahora segun lo que dices entiendo que el unico que se puede mostrar en pantalla es el 0, los demás van destinados a usar texturas. Pero no me cuadra qué pintan los renderbuffers.

He modificado mi mensaje mientras tu escribías el anterior. Así que supongo que no has leido la modificación. Te la pasteo aquí por si te aclara esta duda.

CitarTu piensa que un renderbuffer sirve de contenedor de datos de render, que si bien no los quieres usar como tal, es necesario almacenarlos para renderizar correctamente la escena. Por ejemplo, el depth buffer se suele configurar como renderbuffer y no como texture2d porque lo que tu quieres al final no es el contenido del depth buffer, sino la imagen final. Pero es necesario almacenar en algun sitio el depth buffer para que se renderice correctamente la escena. El color buffer en este caso es el que deberia configurarse como texture 2D porque es lo que buscas utilizar.

Por otra parte, en el caso de hacer shadow mapping, lo que tu quieres es precisamente es contenido del depth buffer. Por lo tanto en este caso configurarias un FBO con una texture 2D como depth attachment y ningún buffer como color attachment. Ya que solo nos interesa el contenido del buffer de profundidad.

¿Me explico?

Cuando lo entiendas todo te parecerá hermoso y perfecto  (ole)  

DraKKaR

 Piensa esto, en tu caso quieres utilizar el color buffer como una textura. Lo primero que se te ocurre es utilizar un FBO con un color attachment como texture2D. Ahora viene el problema: necesitas utilizar el test de profundidad y para ello necesitas un DepthBuffer. ¿Qué depth buffer? El de la pantalla principal no, porque: a) no tiene porque ser del mismo tamaño que tu color attachment y B) no tienes porqué querer que se te machaque el depth buffer principal.

Ahí entran en juego los render buffer. Estableces un DepthBuffer como RenderBuffer para tu FBO y ya tienes un depth buffer que necesitas para hacer correctamente el ZTest. Lo estableces como render buffer y no como texture2D porque no queires para nada su contenido una vez terminado el render. Es como un buffer temporal.

Y para el stencil 3 cuartos de lo mismo.

tamat

 Vale, entonces un renderbuffer es un formalismo. Dado que la escena que quiero renderizar en una textura necesita tener un depthbuffer para que haga los calculos de oclusión correctamente pues tenemos que darle un renderbuffer, pero no interesa que sea el de la pantalla o machacaría los datos de depth que yá tenemos, así que creamos uno aparte y le decimos que use ese. Nosotros no lo leeremos directamente pero tiene que existir para sus calculos. Es así? Pero entonces si creamos un FBO este ocupa memoria extra que solo se usa a veces (ya que he leido que no es recomendable destruirlos cada dos por tres). Bueno, supongo que es un sideeffect.

A todo esto, cuando por mi creo que lo hago todo correctamente me encuentro con que al chequear el status me dice que GL_FRAMEBUFFER_UNSUPPORTED_EXT. Pero tengo una G6600. Necesito instalar algunos drivers nuevos? Yo checkeo si me soporta la extensión mediante glew haciendo un - if (GLEW_EXT_framebuffer_object) - y me cierto, además si pongo las cosas mal entonces me avisa de que no está completeness, pero si lo pongo todo bien salta con que no está soportado.

Alguna idea?
Por un stratos menos tenso

DraKKaR

 Creo que ya tienes clara la teoría.  Aunque no es un formalismo. Necesitas decirle cual es el DepthBuffer. Por ejemplo, podrías crear un único renderbuffer y attachearlo a múltiples FBO diferentes para ahorrar espacio en memoria (siempre que todos tengan el mismo tamaño).

CitarEs así? Pero entonces si creamos un FBO este ocupa memoria extra que solo se usa a veces (ya que he leido que no es recomendable destruirlos cada dos por tres). Bueno, supongo que es un sideeffect.

Cualquier otra opción (como los PBuffers) ocuparían memoria de la misma forma que los FBO, con la desventaja que los PBuffers son mucho mas lentos de intercambiar y no son tan portables. De todas formas, siempre podrías destruir un FBO cuando pase un cierto tiempo después de su utilización (10 segundos por ejemplo, por si la zona en la que estas ya no es visible ese agua con sus efectos de refracción).

CitarA todo esto, cuando por mi creo que lo hago todo correctamente me encuentro con que al chequear el status me dice que GL_FRAMEBUFFER_UNSUPPORTED_EXT. Pero tengo una G6600. Necesito instalar algunos drivers nuevos? Yo checkeo si me soporta la extensión mediante glew haciendo un - if (GLEW_EXT_framebuffer_object) - y me cierto, además si pongo las cosas mal entonces me avisa de que no está completeness, pero si lo pongo todo bien salta con que no está soportado.

Yo en una 6800 Ultra tuve que actualizar los drivers para que me detectara la extensión. Puede que tengas un problema como el que tuve hace tiempo al intentar configurar un FBO con color+depth+stencil. Prueba a configurar un FBO solo con color o con colo+depth a ver si funciona. Puede que necesites la extensión EXT_paked_depth_stencil para conseguir que te funcione el depth+stencil a  la vez. Si sigue sin funcionarte copianos todo tu código de configuración del FBO.

tamat

 Mientras me descargo los ultimos drivers de mi tarjeta (que no se si es exactamente a lo que te refieres por actualizar drivers o hace falta que me baje alguna librería de ogl actualizada?) te pasteo cómo construyo mi FBO:

 // create the frame object
 glGenFramebuffersEXT(1, &mFrameObjectName);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameObjectName);

 // create the textures for the color
 glGenTextures(1, &mFrontTextureName);
 glBindTexture(GL_TEXTURE_2D, mFrontTextureName);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, mFrontTextureName, 0);

 //create and set the depth buffer
 glGenRenderbuffersEXT(1, &mDepthBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mDepthBufferName);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT16,width,height);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthBufferName);


acto seguido chequeo y me da el GL_FRAMEBUFFER_UNSUPPORTED_EXT
Por un stratos menos tenso

DraKKaR

 Prueba a usar GL_DEPTH_COMPONENT24 en vez de GL_DEPTH_COMPONENT16. Por lo demás lo veo bien.

Sí, me refería a actualizar los drivers de la gráfica.  

tamat

 Tela marinera. Me daba el error de los webos porque no había querido definir el tipo de filtrado de las texturas. Para darse con un canto en los dientes. El resultado queda así:

 // create the frame object
 glGenFramebuffersEXT(1, &mFrameObjectName);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameObjectName);

 // create the texture for the color
 glGenTextures(1, &mFrontTextureName);
 glBindTexture(GL_TEXTURE_2D, mFrontTextureName);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,mFrontTextureName, 0);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

 //create and set the depth buffer
 glGenRenderbuffersEXT(1, &mDepthBufferName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mDepthBufferName);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,width,height);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthBufferName);


En fin, muchisimas gracias a todos en especial a Drakkar por la paciencia que ha tenido. :)
Por un stratos menos tenso

DraKKaR

 De nada hombre, a mandar. De todas formas, para acabar de rematarlo:

Según la documentación de glTexParameter, el valor por defecto de GL_TEXTURE_MIN_FILTER es GL_NEAREST_MIPMAP_LINEAR. Esto significaría que por defecto intenta usar mipmapping. Y como no has especificado los mipmaps (solo tienes el nivel base), no te podía dar por completo el FBO. Por eso al cambiar a GL_NEAREST te ha funcionado. Supongo que podrías cambiar a GL_LINEAR para usar el filtrado bilineal y seguiría yendo bien. Y si quieres utilizar mipmapping, puedes decirle que te genere automáticamente los mipmaps cada vez que calcule la textura con GenerateMipmapsEXT de la misma extensión.

Hasta luego!

tamat

 Si ya sabía yo que todo no podía ser tan bonito. Resulta que por alguna extraña razón me salen ciertos artefactos en la imagen, pero solo cuando reduzco el tamaño del buffer mucho.

Si trabajo con una textura de 800x600 entonces la textura contiene la escena perfectamente, la reduzco a 512,512 y sigue todo perfecto, pero si paso de 128x128 entonces empieza a hacer cosas extrañas, hay ciertas regiones en las que no me renderiza las cosas cuando se lo pido (pero otras veces sí), me renderiza solo en algunos recuadros de esas zonas y no siempre (puedo renderizar exactamente la misma escena y a veces me pinta y otras no). Si el mismo objeto que estoy tratando de renderizar en dicha región de la pantalla lo voy moviendo por la escena entonces al salir de la región misteriosa  se renderiza bien.
Es como si hubiese un Depth Buffer asociado e hiciese un depth test que no se cumple, pero tengo el DepthTest desactivado (no hay duda de esto.

Tiene toda la pinta de que se me solapan bufferes o algo, tal vez el buffer alpha, no se. Pero no tiene para nada pinta de ser problema de mi codigo sino más bien de solapación de bufferes. Dejo a continuación el codigo con el cual creo mi FBO:

 // create the frame object
 glGenFramebuffersEXT(1, &mFrameObjectName);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameObjectName);

 // create the texture for the color
 glGenTextures(1, &mFrontTextureName);
 glBindTexture(GL_TEXTURE_2D, mFrontTextureName);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D,mFrontTextureName, 0);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

 glGenRenderbuffersEXT(1, &mDepthTextureName);
 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,mDepthTextureName);
 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,width,height);
 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepthTextureName);


Y aquí una muestra gráfica del error:

En la parte de arriba está cómo debería renderizar el texto (y como se ve lo hace) pero parpadea y hace cosas raras como lo que se ve en la mitad de abajo. Si os fijais vereis que se aprecia claramente como no pinta regiones cuadradas de varios pixeles de ancho.


Entiendo que es un error bastante chungo, pero quien sabe si alguien me puede ayudar. Gracias.
Por un stratos menos tenso






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.