Quel état est stocké dans un objet VAO (OpenGL Artex Array Object) et comment utiliser correctement le VAO?

25

Je me demandais quel état est stocké dans un VAO OpenGL. J'ai compris qu'un VAO contient un état lié aux spécifications des sommets des sommets tamponnés (quels attributs sont dans les tampons et quels tampons sont liés, ...). Pour mieux comprendre l'utilisation correcte des VAO, j'aimerais savoir exactement dans quel état ils se trouvent.


Comment je suppose que les VAO doivent être utilisés

À partir d'exemples simples, j'ai compris que l'utilisation correcte des VAO est la suivante:

Installer

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

Le rendu

Bind VAO
---- Draw
Unbind VAO

De cela, je suppose qu'au moins les liaisons de tampon de sommet et les spécifications d'attribut de sommet sont stockées dans le VAO. Je ne sais pas cependant comment ce modèle d'utilisation s'étend aux situations où (plusieurs) textures et (multiples) programmes de shader entrent en jeu. Le programme de shader actif est-il stocké dans le VAO? Et les liaisons de texture (avec leurs paramètres d'échantillonnage / d'emballage ) sont-elles également stockées dans le VAO? Idem pour les uniformes ?


Par conséquent, mes questions sont les suivantes:

  • Quel état exact est stocké dans un VAO OpenGL ? (Liaisons VBO, spécifications d'attributs, programme de shader actif, liaisons de texture, paramètres d'échantillonnage / habillage de texture, uniformes ...?)
  • Comment utiliser correctement les VAO dans une configuration de rendu plus complexe où (plusieurs) textures avec des paramètres d'échantillonnage / habillage associés, (plusieurs) programmes de shader et uniformes sont impliqués?
Jelle van Campen
la source
1
VAO stocke des données sur les emplacements des attributs de sommet. Il stocke également les ID des VBO dans lesquels ces attributs sont contenus. Vous n'avez pas besoin de lier VBO lorsque vous dessinez quelque chose, vous devez le lier avant d'appeler glVertexAttribPointer () lorsque vous créez VAO.
HolyBlackCat

Réponses:

18

VAO stocke des données sur les emplacements des attributs de sommet. (Et certaines autres données qui leur sont liées.)
"VBO bindings, active shader program, texture bindings, texture sampling/wrapping settings, uniforms"N'y sont absolument pas liées.

Vous pouvez vous demander pourquoi il ne se souvient pas de la liaison VBO. Parce que vous n'avez pas besoin de lier VBO pour dessiner quelque chose, vous devez seulement le lier lors de la création de VAO: Lorsque vous appelez glVertexAttribPointer(...), VAO se souvient de quel VBO est actuellement lié. Et VAO prendra les attributs de ces VBO lorsque vous le dessinerez, même si ces VBO ne sont pas liés actuellement.


De plus, les VAO et les VBO doivent être utilisés légèrement différemment:

Cela ne fonctionnera pas

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

car vous devez lier VBO pour spécifier les emplacements des attributs.

Donc, vous devriez le faire comme ceci:

Generate VAO
BindVAO
Generate VBO's
BindVBO's
Specify vertex attributes

Vous pouvez modifier les données de VBO à tout moment, mais vous devez les lier avant.

Et le dessin devrait ressembler à ceci:

Bind VAO
Draw


Comme vous l'avez peut-être remarqué, j'ai supprimé les unbindappels de vos listes. Ils sont presque complètement inutiles et ils ralentiront légèrement votre programme, donc je ne vois aucune raison de les appeler.

HolyBlackCat
la source
9
"donc je ne vois aucune raison de les appeler." pour éviter de les changer accidentellement. Surtout un problème lors de l'utilisation de bibliothèques tierces.
ratchet freak du
Merci pour la bonne réponse! Donc, en bref, le VAO ne stocke que les emplacements des attributs de sommet. Les VBO ne sont pas rebondis lors de la liaison d'un VAO, car le VAO sait dans quels tampons trouver les attributs. Tous les autres états sont contenus dans l'état OpenGL global.
Jelle van Campen
@JellevanCampen Oui, correct. Pour info, il stocke également l'état off / on des attributs ( gl{Enable|Disable}VertexAttribArray()), leurs valeurs par défaut ( glVertexAttrib*()), leur mode d'instanciation ( glVertexAttribDivisor()) et probablement autre chose.
HolyBlackCat
@HolyBlackCat êtes-vous sûr que l'état par défaut (glVertexAttrib ()) fait partie de l'état VAO? Le wiki OpenGL affirme le contraire, affirmant qu'il s'agit d'un état de contexte.
rdb
@ndb Non, je ne suis pas sûr. Je m'attendais à ce qu'ils fassent partie de l'État VAO, et je ne l'ai pas vérifié.
HolyBlackCat
4

Il stocke uniquement la liaison de sommet et la liaison de tampon d'index

Il s'agit de tous les paramètres de glVertexAttribPointerplus le tampon lié à Vertex_Array_buffer au moment de l'appel à glVertexAttribPointeret le Element_Array_buffer lié.

Les uniformes font partie du programme actuel.

Tout le reste est un état global.

Dans le doute, vous pouvez vérifier les tables d'état dans les spécifications de la version que vous utilisez.

monstre à cliquet
la source
Merci aussi pour la réponse! Cela clarifie les choses pour moi.
Jelle van Campen
4

Voici une explication simple mais efficace, fondamentalement, un objet tampon contient des informations qui peuvent être interprétées comme de simples bits de données brutes, ce qui en soi ne signifie rien, il s'agit donc purement et simplement de données qui peuvent être consultées de toute façon.

i.e float vbo[]={1.0,2.0,34.0...}

et la façon dont OpenGL a été conçu pour fonctionner est que vous devez DÉFINIR à quoi les données que votre passage aux différents shaders va ressembler pour les shaders

en ce que vous devez également définir comment il lira ces données, dans quel format elles sont, et quoi en faire et comment elles seront utilisées et pour quoi, toutes ces informations sont stockées dans le VAO

par exemple, vous pouvez déclarer des données stockées dans un tableau comme celui-ci float vbo = {11.0,2.0,3.0,4.0}

ce qui est nécessaire ensuite à ce stade est de savoir comment interpréter ces données du VBO dans le VAO, et ce que cela signifie est comme suit

le VAO peut être réglé pour lire 2 flotteurs par sommet (ce qui en ferait 2 vecteurs à deux dimensions x, y) ou vous pouvez dire au vao de l'interpréter comme 1 vecteur à 4 dimensions, c'est-à-dire x, y, z, w, etc.

mais aussi d'autres attributs de ces données sont définis et stockés dans le VAO tels que le format de données (malgré que vous ayez déclaré un tableau de float, vous pouvez dire au shader de le lire sous forme d'entier, avec bien sûr le système convertissant les données brutes en le processus de float à integer et a son propre ensemble de règles que faire dans de telles circonstances)

Donc, fondamentalement, le VBO est les données, et le VAO stocke comment interpréter ces données, car les shaders et le serveur OpenGL sont conçus pour être très curieux et doivent tout savoir avant de décider comment les traiter et quoi en faire et où pour le dire

bien sûr, ce n'est pas vraiment curieux, il semble en fait être le plus efficace car il doit stocker ces données dans la mémoire du serveur graphique afin d'obtenir le traitement le plus efficace et le plus rapide (à moins qu'il ne décide qu'il n'a pas besoin de le faire si les données ne doivent pas être traitées de cette manière et utilisées pour d'autres informations qui ne sont pas souvent consultées), et donc pourquoi les détails de ce qu'il faut faire avec les données et comment les traiter doivent être stockés dans le VAO, donc le VAO est comme un en-tête et le VBO est comme les données brutes pures que l'en-tête utilise et définit (dans ce cas, passe aux attributs de vertex du shader) à l'exception que le VBO n'est pas limité à être utilisé uniquement par un VAO, il peut être utilisé et réutilisé et lié à de nombreux VAO, par exemple:

ce que vous pouvez faire, c'est que vous pouvez lier un objet tampon à VAO1 et également (séparément) lier le même objet tampon à VAO2 avec chacun l'interprétant différemment de sorte que si votre shader où traiter les données, selon quel VAO est celui qui est lié, il traiterait les mêmes données brutes différemment du frambuffer (dessin des pixels dans la fenêtre) résultant en un affichage différent des mêmes données qui serait basé sur la façon dont vous avez défini leur utilisation dans le VAO

hopjopper
la source
C'est la meilleure réponse!
CodingMadeEasy