Je veux juste m'assurer que je comprends bien (je demanderais sur SO Chat, mais c'est mort dedans!):
Nous avons un tableau de sommets que nous rendons "courant" en le liant
alors nous avons un tampon, que nous lions à une cible
puis nous remplissons cette cible via glBufferData
qui renseigne essentiellement tout ce qui était lié à cette cible, c'est-à-dire notre tampon
et ensuite nous appelons glVertexAttribPointer
qui décrit comment les données sont présentées - les données étant ce qui est lié à GL_ARRAY_BUFFER
et ce descripteur est sauvegardé dans notre Vertex Array original
(1) Est-ce que ma compréhension est correcte?
Le documentation est un peu clair sur la façon dont tout est en corrélation.
(2) Existe-t-il une sorte de matrice de sommets par défaut? Parce que j'ai oublié/omis glGenVertexArrays
et glBindVertexArray
et mon programme a bien fonctionné sans cela.
Edit: J'ai raté une étape ... glEnableVertexAttribArray
.
(3) Est-ce que l'attribut de sommet est lié au tableau de sommets au moment où glVertexAttribPointer
est appelé, puis nous pouvons activer/désactiver cet attribut via glEnableVertexAttribArray
à tout moment, quel que soit le sommet de sommets actuellement lié?
Ou bien (3b) Est-ce que l'attribut de sommet est lié au tableau de sommets au moment où glEnableVertexAttribArray
est appelé, et nous pouvons donc ajouter le même attribut de sommet à plusieurs tableaux de sommets en appelant glEnableVertexAttribArray
à des moments différents, quand différents réseaux de sommets sont liés?
Une partie de la terminologie est un peu décalée:
Vertex Array
Est juste un tableau (généralement un float[]
) Qui contient des données de sommet. Il n'a pas besoin d'être lié à quoi que ce soit. Ne pas confondre avec un Vertex Array Object
Ou un VAO, que je reviendrai plus tardBuffer Object
, Communément appelé Vertex Buffer Object
Lors du stockage de sommets, ou VBO, est ce que vous appelez simplement un Buffer
.glVertexAttribPointer
fonctionne exactement comme glVertexPointer
ou glTexCoordPointer
, mais au lieu d'attributs nommés, vous devez fournir un nombre spécifiant votre propre attribut. . Vous transmettez cette valeur sous la forme index
. Tous vos appels glVertexAttribPointer
sont mis en file d'attente pour votre prochain appel à glDrawArrays
ou glDrawElements
. Si vous avez une liaison VAO, le VAO stockera les paramètres de tous vos attributs.Le problème principal ici est que vous confondez les attributs de sommet avec les VAO. Les attributs de sommet ne sont que la nouvelle façon de définir les sommets, les texcoords, les normales, etc. pour le dessin. Etat des magasins VAO. Je vais d'abord expliquer le fonctionnement du dessin avec les attributs de sommet, puis expliquer comment vous pouvez réduire le nombre d'appels de méthode avec des VAO:
glEnableVertexAttribArray(0);
.glBindBuffer(GL_ARRAY_BUFFER, myBuffer);
.glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
. Dans l'ordre du paramètre: 0 est l'attribut que vous définissez, 3 est la taille de chaque sommet, GL_FLOAT
Est le type, GL_FALSE
Signifie ne pas normaliser chaque sommet, la moyenne des deux derniers zéros qu'il n'y a pas de foulée ou d'offset sur les sommets.glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(0);
Enveloppez cela dans les appels glUseProgram()
et vous obtenez un système de rendu qui fonctionne correctement avec les shaders. Mais disons que vous avez 5 attributs différents, sommets, texcoords, normales, couleurs et coordonnées lightmap. Tout d'abord, vous ne feriez qu'un seul appel glVertexAttribPointer
pour chacun de ces attributs et vous devrez préalablement activer tous les attributs. Supposons que vous définissiez les attributs 0 à 4 tels qu'ils sont énumérés. Vous les activeriez tous comme ceci:
for (int i = 0; i < 5; i++)
glEnableVertexAttribArray(i);
Et vous devrez alors lier différents VBO pour chaque attribut (à moins que vous ne les stockiez tous dans un seul VBO et utilisiez des décalages/stride), vous devez alors effectuer 5 appels différents glVertexAttribPointer
, à partir de glVertexAttribPointer(0,...);
to glVertexAttribPointer(4,...);
pour les sommets aux coordonnées lightmap, respectivement.
Espérons que ce système seul a du sens. Je vais maintenant passer aux VAO pour leur expliquer comment les utiliser pour réduire le nombre d'appels de méthode lors de ce type de rendu. Notez que l'utilisation d'un ordinateur VAO n'est pas nécessaire.
Un Vertex Array Object
Ou un VAO est utilisé pour stocker l'état de tous les appels glVertexAttribPointer
et des VBO ciblés lors de chacun des appels glVertexAttribPointer
.
Vous en générez un avec un appel à glGenVertexArrays
. Pour stocker tout ce dont vous avez besoin dans un VAO, associez-le avec glBindVertexArray
puis faites un appel de tirage complet. Tous les dessiner les appels de liaison sont interceptés et stockés par le VAO. Vous pouvez dissocier le VAO avec glBindVertexArray(0);
Maintenant, lorsque vous voulez dessiner l'objet, vous n'avez pas besoin de rappeler toutes les liaisons VBO ou les appels glVertexAttribPointer
, il vous suffit de lier le VAO avec glBindVertexArray
, puis d'appeler glDrawArrays
ou glDrawElements
et vous dessinerez exactement la même chose que si vous utilisiez tous ces appels de méthode. Vous voudrez probablement également dissocier le VAO par la suite.
Une fois que vous avez dissocié le VAO, tous les états retrouvent leur état antérieur à la liaison du VAO. Je ne sais pas si les modifications que vous apportez pendant que le VAO est lié sont conservées, mais cela peut facilement être compris avec un programme de test. Je suppose que vous pouvez imaginer que glBindVertexArray(0);
soit lié au VAO "par défaut" ...
Mise à jour: Quelqu'un m'a signalé le besoin d'un appel de tirage au sort. En fin de compte, vous n'avez pas besoin de faire un appel de tirage COMPLET lors de la configuration du VAO, mais seulement de tout ce qui vous lie. Je ne sais pas pourquoi je pensais que c'était nécessaire plus tôt, mais c'est corrigé maintenant.
La terminologie et la séquence des API à appeler sont assez déroutantes. Ce qui est encore plus déroutant, c'est comment les différents aspects - tampon, attribut de sommet générique et variable d'attribut shader sont associés. Voir Terminologie OpenGL pour une très bonne explication.
De plus, le lien OpenGL-VBO, shader, VAO montre un exemple simple avec les appels d'API nécessaires. C'est particulièrement intéressant pour ceux qui passent du mode immédiat au pipeline programmable.
J'espère que ça aide.
Edit: Comme vous pouvez le constater à partir des commentaires ci-dessous, les utilisateurs peuvent émettre des hypothèses et avancer rapidement aux conclusions. La réalité est que c'est assez déroutant pour les débutants.