Obtenir une texture à partir d'un rendu de tampon dans OpenGL?

13

J'ai un tampon de rendu (DepthStencil) dans un FBO et j'ai besoin d'en obtenir une texture. Je ne peux pas avoir à la fois une texture DepthComponent et un renduerbuffer DepthStencil dans le FBO, il me semble donc j'ai besoin d'un moyen de convertir le renduerbuffer en une texture DepthComponent une fois que j'en aurai fini pour l'utiliser plus tard dans le pipeline.

J'ai essayé de nombreuses techniques pour saisir le composant de profondeur du renduerbuffer pendant des semaines, mais je sors toujours avec des ordures. Tout ce que je veux à la fin, c'est la même texture que j'obtiendrais d'un FBO si je n'utilisais pas de rendu de tampon. Quelqu'un peut-il publier des instructions complètes ou du code couvrant cette opération apparemment simple?

ÉDITER:

Linky vers une version extraite du code http://dl.dropbox.com/u/9279501/fbo.cs

Screeny de l'effet Depth of Field + FBO - sans profondeur (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Screeny sans effet de profondeur de champ + FBO - profondeur de travail fine http://i.stack.imgur.com/boOm1.jpg

Rushyo
la source

Réponses:

2

Alternativement, vous pouvez simplement passer d'un FBO à un autre, comme celui basé sur un rendu de tampon et un basé sur la texture. Je le fais de cette façon:

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

(Dans votre cas, lorsque vous souhaitez effectuer un tampon de profondeur, vous pouvez utiliser GL_DEPTH_BUFFER_BIT au lieu de GL_COLOR_BUFFER_BIT)

Après avoir fusionné dans le rendu de tampon basé sur la texture, vous pouvez ensuite utiliser la texture normalement; en le passant dans des shaders comme uniforme ou comme vous voulez.

Trevor Powell
la source
1

Non, ce n'est pas possible. Tout au plus, vous pouvez glReadPixels les données vers le CPU, et en créer une texture, mais cela sera lourd et lent. Les tampons de rendu ne sont pas faits pour cela, cette fonctionnalité n'est fournie que par des textures.

Matias Valdenegro
la source
Compte tenu de cela, quelle est l'alternative? Comment pouvez-vous maintenir la profondeur dans votre tampon de dessin et acquérir également la composante de profondeur en tant que texture?
Rushyo
@Rushyo: Une alternative pourrait être de se débarrasser de la mémoire tampon du pochoir (si possible!) Et de faire du tampon de rendu de profondeur une texture de profondeur. Pourquoi utilisez-vous un pochoir?
Calvin1602
Essentiellement chaque fois que j'acquiert la texture de profondeur, mes tests de profondeur se cassent. Si j'attache un attachement de profondeur à mon FBO, le FBO n'écrit aucune information de profondeur ailleurs - donc quand j'essaie de récupérer l'attachement de couleur il n'y a pas de test de profondeur dessus (ce qui est normalement le cas si je n'ai pas d'attachement de profondeur ). J'ai essayé toutes les combinaisons auxquelles je peux penser, y compris la méthode «lourde et lente» susmentionnée. Quoi que je fasse, je ne peux pas obtenir à la fois un rendu «typique» de ma scène dans une texture et juste la profondeur dans une autre.
Rushyo
@ Calvin1602 Quand je barbotais avec le renduerbuffer, j'ai trouvé que l'utilisation de l'attachement de profondeur sans l'attachement du pochoir produisait des résultats indésirables.
Rushyo
@Rushyo Je parie que vous ne configurez pas la texture correctement, le code de publication nous permettra d'aider :)
Matias Valdenegro
1

Ce que vous demandez est possible dans OpenGL 3.2. J'ai mon FBO qui crache une couleur diffuse en une texture de couleur, des normales en une autre texture de couleur et une profondeur en une texture de profondeur - aucun tampon de rendu n'est nécessaire. En fait, les rendus de tampons ne sont qu'un problème, car vous ne pouvez pas en échantillonner, vous devez donc utiliserglReadPixels(...) ou autrement copier les données hors du RBO et dans une texture sur le CPU, au lieu de simplement tout conserver dans la mémoire du GPU. Donc...

Si vous le souhaitez vraiment, vous pouvez écrire du code dans votre shader de premier passage pour sortir manuellement des éléments tels que la profondeur, dans une pièce jointe de texture de couleur distincte dans votre FBO. Ce serait pour vous dans vos shaders post-pass. Pour l' utilisation d'OpenGL dans ses tests de profondeur internes, vous auriez également besoin d'un RBO ou d'un ensemble de textures comme GL_DEPTH_ATTACHMENT de votre FBO. Mais vous pouvez configurer une seule texture pour servir les deux - c'est plus efficace et plus facile à utiliser.

Mon code de configuration de texture de profondeur ressemble à ceci (Java, ignorez simplement le truc ByteBuffer ... et notez que j'utilise "id" pour faire référence aux poignées / pointeurs entiers, car ce concept ne fonctionne pas vraiment 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);

Et ensuite:

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

Vous pouvez maintenant passer gBufferDepthTexture(ou ce que vous avez) comme uniforme à vos shaders de fragments de deuxième et troisième passes. Je pense que nous pouvons supposer en toute sécurité que vous pouvez faire exactement la même chose avec le tampon de gabarit.

Ingénieur
la source
0

Vous devriez pouvoir créer une texture (au lieu d'un RenderBuffer) en utilisant le format GL_DEPTH_STENCIL. Je ne suis pas sûr du processus exact d'utilisation de la profondeur d'une telle texture dans un programme de shader (que je suppose que vous utilisez, car vous utilisez des FBO), mais la spécification OpenGL devrait spécifier quels canaux de couleur obtiennent quelles valeurs ( ma conjecture serait que R, G et B sont tous mis à la profondeur et A est réglé au pochoir).

Je cible OpenGL 3.2 ces jours-ci, vous devrez donc peut-être vérifier que le format de texture est réalisable pour vous. Je ne me souviens jamais quelles versions présentent différentes fonctionnalités.

Branan
la source
Le problème n'est alors pas de capturer le composant GL_DEPTH_STENCIL dans une texture, mais le fait que toutes les informations de profondeur sont perdues dans le FBO chaque fois que vous le faites. Le FBO devient inutile pour ensuite rendre la scène dans le tampon de dessin. Par conséquent, j'utilisais un Renderbuffer dans l'espoir de contourner ce problème. Je pense que pour l'instant je n'ai pas d'autre choix que de faire deux passes pour saisir la profondeur + dessiner les informations séparément = (cher comme l'enfer jusqu'à ce que je puisse trouver un moyen de le contourner.
Rushyo
@Rushyo J'ai posté une réponse à cette ancienne question :) Vous voudrez peut-être y jeter un coup d'œil, bien que vous ayez probablement résolu il y a quelques années.
Ingénieur
@NickWiggill je souhaite! Fudged quelque chose et a continué ma vie. Je ne peux pas réellement tester votre réponse avant d'avoir recréé les ressources que j'ai utilisées dans ce prototype. Pourrait y arriver à un moment donné ...
Rushyo