Que sont les objets Vertex Array?

114

Je commence tout juste à apprendre OpenGL aujourd'hui à partir de ce tutoriel: http://openglbook.com/the-book/
Je suis arrivé au chapitre 2, où je dessine un triangle, et je comprends tout sauf les VAO (cet acronyme est-il correct?). Le tutoriel a ce code:

glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);

Bien que je comprenne que le code est nécessaire, je n'ai aucune idée de ce qu'il fait. Bien que je n'utilise jamais VaoId au-delà de ce point (sauf pour le détruire), le code ne fonctionne pas sans lui. Je suppose que c'est parce qu'il est nécessaire d'être lié, mais je ne sais pas pourquoi. Ce code exact doit-il simplement faire partie de chaque programme OpenGL? Le didacticiel explique les VAO comme suit:

Un objet Vertex Array (ou VAO) est un objet qui décrit comment les attributs de vertex sont stockés dans un objet Vertex Buffer (ou VBO). Cela signifie que le VAO n'est pas l'objet réel stockant les données de sommet, mais le descripteur des données de sommet. Les attributs Vertex peuvent être décrits par la fonction glVertexAttribPointer et ses deux fonctions soeurs glVertexAttribIPointer et glVertexAttribLPointer, la première que nous explorerons ci-dessous.

Je ne comprends pas comment le VAO décrit les attributs de vertex. Je ne les ai décrits d’aucune façon. Obtient-il les informations du glVertexAttribPointer? Je suppose que ça doit être ça. Le VAO est-il simplement une destination pour les informations de glVertexAttribPointer?

En passant, le tutoriel que je suis est-il acceptable? Y a-t-il quelque chose à surveiller ou un meilleur tutoriel à suivre?

Patrick
la source

Réponses:

100

"Vertex Array Object" vous est présenté par le sous-comité OpenGL ARB pour les noms stupides.

Considérez-le comme un objet géométrique. (En tant qu'ancien programmeur SGI Performer, je les appelle des géosets.) Les variables / membres d'instance de l'objet sont votre pointeur de sommet, pointeur normal, pointeur de couleur, pointeur attrib N, ...

Lors de la première liaison d'un VAO, vous attribuez ces membres en appelant

glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer...;
glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer...;

etc. Les attributs activés et les pointeurs que vous fournissez sont stockés dans le VAO.

Après cela, lorsque vous liez à nouveau le VAO, tous ces attributs et pointeurs deviennent également actifs. Ainsi, un glBindVertexArrayappel équivaut à tout le code nécessaire auparavant pour configurer tous les attributs. C'est pratique pour passer de la géométrie entre des fonctions ou des méthodes sans avoir à créer vos propres structures ou objets.

(Une configuration unique, une utilisation multiple est le moyen le plus simple d'utiliser les VAO, mais vous pouvez également modifier les attributs simplement en les liant et en effectuant plus d'appels d'activation / de pointeur. Les VAO ne sont pas des constantes.)

Plus d'infos en réponse aux questions de Patrick:

La valeur par défaut pour un VAO nouvellement créé est qu'il est vide (AFAIK). Pas de géométrie du tout, pas même de sommets, donc si vous essayez de le dessiner, vous obtiendrez une erreur OpenGL. Ceci est raisonnablement sain, comme dans "tout initialiser à False / NULL / zero".

Vous n'en avez besoin que glEnableClientStatelorsque vous configurez les choses. Le VAO se souvient de l'état d'activation / de désactivation de chaque pointeur.

Oui, le VAO stockera glEnableVertexAttribArrayet glVertexAttrib. Les anciens tableaux de sommets, normaux, couleurs, ... sont les mêmes que les tableaux d'attributs, vertex == # 0 et ainsi de suite.

Hugh
la source
62
"Vertex Array Object" vous est présenté par le sous-comité OpenGL ARB pour les noms stupides. Oui, un nom tellement idiot pour un objet qui stocke les liaisons de tableaux de sommets .
Nicol Bolas
2
De plus, les VAO sont-ils liés àglVertexAttribPointer
Patrick
2
Veuillez ajouter des informations sur l'utilisation des attributs de sommet génériques pour les personnes qui utilisent le profil principal.
Oskar
8
@NicolBolas Un meilleur nom serait VertexArrayMacroou quelque chose de similaire.
bobobobo
7
@NicolBolas "Vertex Array Object" est un nom affreux. Il s'agit de lier les données aux attributs . Il ne s'agit pas d'un tableau de sommets, comme son nom l'indique. Il n'y a aucune référence à des liaisons ou des attributs dans le nom, et comme le «tableau de sommets» est un concept séparé lui-même, il rend la compréhension encore plus difficile. À mon humble avis, "(Vertex) Attributes Binding Object" est plus facile à comprendre. Même Geometry Object est meilleur: je ne l'aime pas, mais au moins il n'est pas surchargé.
AkiRoss
8

Les objets Vertex Array sont comme des macros dans les programmes de traitement de texte, etc. Une bonne description se trouve ici .

Les macros se souviennent simplement des actions que vous avez effectuées, telles que activer cet attribut, lier ce tampon, etc. Lorsque vous appelez glBindVertexArray( yourVAOId ), il relit simplement ces liaisons de pointeur d'attribut et de tampon.

Ainsi, votre prochain appel à dessiner utilise ce qui était lié par le VAO.

Les VAO ne stockent pas les données de sommet . Non. Les données de vertex sont stockées dans un tampon de vertex ou dans un tableau de mémoire client.

bobobobo
la source
19
-1: Ce ne sont pas comme des macros. Si tel était le cas, la liaison d'un nouveau VAO ne désactiverait pas les tableaux de sommets activés par un VAO précédent, à moins que le nouveau VAO n'ait "enregistré" votre désactivation explicite de ces tableaux. Les VAO, comme tous les objets OpenGL, conservent l' état , pas les commandes. Les commandes changent simplement d' état, mais les objets sont fournis avec un état par défaut. C'est pourquoi la liaison d'un VAO nouvellement créé désactivera toujours tous les attributs.
Nicol Bolas
6

Je considère toujours VAO comme un tableau de tampons de données utilisés par OpenGL. En utilisant OpenGL moderne, vous allez créer des objets VAO et Vertex Buffer.

entrez la description de l'image ici

//vaoB is a buffer
glGenVertexArrays(1, vaoB); //creates one VAO
glBindVertexArray(vao.get(0));
glGenBuffers(vbo.length, vbo, 0); //vbo is a buffer
glBindVertexArray(vao.get(1));
glGenBuffers(vbo1.length, vbo1, 0); //vbo1 is a buffer
glBindVertexArray(vao.get(2));
glGenBuffers(vbo2.length, vbo2, 0); //vbo2 is a buffer

L'étape suivante consiste à lier les données à un tampon:

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER,vertBuf.limit()*4, vertBuf, GL_STATIC_DRAW); //vertf buf is a floatbuffer of vertices

À ce stade, OpenGL voit:

entrez la description de l'image ici

Nous pouvons maintenant utiliser glVertexAttribPointer pour indiquer à OpenGL ce que représentent les données du tampon:

glBindBuffer(GL_ARRAY_BUFFER, 0); //bind VBO at 0
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); //each vertex has 3 components of size GL_FLOAT with 0 stride (space) between them and the first component starts at 0 (start of data)

entrez la description de l'image ici

OpenGL a maintenant les données dans le tampon et sait comment les données sont organisées en sommets. Le même processus peut être appliqué aux coordonnées de texture, etc., mais pour les coordonnées de texture, il y aurait deux valeurs.

glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER,coordBuf.limit()*4, coordBuf, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);

Ensuite, vous pouvez lier la texture et dessiner des tableaux, vous voudrez créer un shader Vert et Frag, le compiler et le joindre à un programme (non inclus ici).

glActiveTexture(textureID); //bind our texture
glBindTexture(GL_TEXTURE_2D, textureID);
glDrawArrays(GL_TRIANGLES,0,6); //in this case 6 indices are used for two triangles forming a square
vasmos
la source
5

VAO est un objet qui représente l'étape d'extraction de vertex du pipeline OpenGL et est utilisé pour fournir une entrée au nuanceur de vertex.

Vous pouvez créer un objet de tableau de sommets comme celui-ci

GLuint vao;
glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);

Commençons par faire un exemple simple. Considérez un tel paramètre d'entrée dans un code de shader

layout (location = 0) in vec4 offset; // input vertex attribute

Pour remplir cet attribut, nous pouvons utiliser

glVertexAttrib4fv(0, attrib); // updates the value of input attribute 0

Bien que l'objet tableau de sommets stocke ces valeurs d'attributs statiques pour vous, il peut faire beaucoup plus.

Après avoir créé un objet de tableau de sommets, nous pouvons commencer à remplir son état. Nous demanderons à OpenGL de le remplir automatiquement en utilisant les données stockées dans un objet tampon que nous fournissons. Chaque attribut de sommet récupère des données à partir d'un tampon lié à l'une des nombreuses liaisons de tampon de sommet. Pour cela, nous utilisons glVertexArrayAttribBinding(GLuint vao, GLuint attribindex, GLuint bindingindex). Nous utilisons également la glVertexArrayVertexBuffer()fonction pour lier un tampon à l'une des liaisons de tampon de vertex. Nous utilisons la glVertexArrayAttribFormat()fonction pour décrire la mise en page et le format des données, et enfin nous activons le remplissage automatique de l'attribut en appelant glEnableVertexAttribArray().

Lorsqu'un attribut de sommet est activé, OpenGL fournira des données au shader de sommet en fonction du format et des informations d'emplacement que vous avez fournis avec glVertexArrayVertexBuffer()et glVertexArrayAttribFormat(). Lorsque l'attribut est désactivé, le vertex shader recevra les informations statiques que vous fournissez lors d'un appel glVertexAttrib*().

// First, bind a vertex buffer to the VAO
glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(vmath::vec4));

// Now, describe the data to OpenGL, tell it where it is, and turn on automatic
// vertex fetching for the specified attribute
glVertexArrayAttribFormat(vao, 0, 4, GL_FLOAT, GL_FALSE, 0);

glEnableVertexArrayAttrib(vao, 0);

Et coder dans un shader

layout (location = 0) in vec4 position;

Après tout, vous devez appeler glDeleteVertexArrays(1, &vao).


Vous pouvez lire OpenGL SuperBible pour mieux le comprendre.

Yola
la source
3
Il est bon de voir des gens promouvoir l'utilisation d'OpenGL de style DSA.
Nicol Bolas