2009-03-06 8 views
0

J'ai un peu de code OpenGL qui se comporte de manière incohérente sur différents matériels . J'ai un code qui:Auto-Référencement Renderbuffers dans OpenGL

  1. Crée un rendu tampon et se fixe une texture à sa mémoire tampon de couleur (Texture A)
  2. Définit ce rendu tampon actif, et ajuste la fenêtre, etc
  3. Active un pixel shader (flou gaussien, dans ce cas).
  4. Dessine un quad en plein écran avec la texture A dessus.
  5. Annule la liaison renderbuffer, etc.

Sur ma machine de développement cela fonctionne très bien, et a pour effet prévu de brouiller la texture « en place », mais sur d'autres matériels cela ne semble pas fonctionner.

Je l'ai réduit à deux possibilités. A) Rendre un renderbuffer rendu à lui-même n'est pas censé fonctionner, et ne fonctionne que sur ma machine de développement en raison d'une sorte de coup de chance.

Ou

B) Cette approche devrait fonctionner, mais quelque chose d'autre va mal.

Des idées? Honnêtement, j'ai eu du mal à trouver des détails sur cette question.

Répondre

2

A) est la bonne réponse. Rendu dans le même tampon lors de la lecture est indéfini. Ça pourrait marcher, ça pourrait ne pas être - ce qui est exactement ce qui se passe.

Dans le cas d'OpenGL, framebuffer_object extension a la section "4.4.3 Rendu lorsqu'une image d'un objet de texture liée est également attachée au framebuffer" qui indique ce qui se passe (fondamentalement, indéfini). Dans Direct3D9, le runtime de débogage se plaint bruyamment si vous utilisez cette configuration (mais cela peut fonctionner selon le matériel/pilote). En D3D10, le runtime délie toujours la cible utilisée comme destination, je pense.

Pourquoi cela est-il indéfini? L'une des raisons pour lesquelles les GPU sont si rapides est qu'ils peuvent faire beaucoup de suppositions. Par exemple, ils peuvent supposer que les unités qui récupèrent des pixels n'ont pas besoin de communiquer avec des unités qui écrivent des pixels. Donc une surface peut être lue, N cycles plus tard la lecture est terminée, N cycles plus tard, le pixel shader termine son exécution, puis il met dans certains tampons de fusion en sortie sur le GPU, et finalement il est écrit en mémoire. De plus, les GPU se rastérisent dans un ordre "indéfini" (un GPU peut rasteriser en rangées, un autre en cache, un autre en un tout autre ordre), donc vous ne savez pas quelles parties de la surface seront écrites au premier.

Donc, ce que vous devez faire est de créer plusieurs tampons. Dans le cas de flou/lueur, deux est généralement suffisant - rendre en premier, puis lire & flou que lors de l'écriture en deuxième. Répétez ce processus si nécessaire de manière ping-pong.

+0

Merci, je penche pour cela dans mes propres recherches, même si je n'ai pas pu obtenir de réponse concrète. – Brandorf

+0

@brandorf: J'ai ajouté un lien vers la spécification d'objet framebuffer où il est dit que le résultat n'est pas défini. – NeARAZ

0

Dans certains cas particuliers, même le backbuffer peut suffire. Vous ne faites simplement pas de GlClear, et ce que vous avez dessiné précédemment est toujours là. La mise en garde est, bien sûr, que vous ne pouvez pas vraiment lire à partir du backbuffer. Mais pour des effets comme l'effacement et l'effacement, cela fonctionne.