OpenGL Moderne

Tutoriel 9 : indexation de VBO

Opengl-tutorial.org

Traducteur

Alexandre Laurent

Jusqu'à présent, lors de la construction du VBO, on avait dupliqué les sommets à chaque fois que deux triangles partageaient un côté.

Dans ce tutoriel, on va discuter de l'indexation, qui permet de réutiliser le même sommet encore et encore. Cela est possible grâce au tampon d'indices.

Commentez

- Titre : OpenGL Moderne

- Auteur : Opengl-tutorial.org

- Traducteur : Alexandre Laurent

- Parution : 20 mai 2014

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2014 opengl-tutorial.org. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Navigation

- I. Le principe de l'indexation

- II. Partagé contre séparé

- III. VBO indexé en OpenGL

- IV. Remplir le tampon d'indices

- V. Extra : le compteur de FPS

- VI. Remerciements

- Navigation

Navigation

Tutoriel précédent : shaders de base

Sommaire

Tutoriel suivant : la transparence

I - Le principe de l'indexation

Jusqu'à présent, lors de la construction du VBO, on avait dupliqué les sommets à chaque fois que deux triangles partageaient un côté.

Dans ce tutoriel, on va s'initier à l'indexation, qui permet de réutiliser le même sommet encore et encore. Cela est possible grâce au tampon d'indices.

Le tampon d'indices contient des entiers, trois pour chaque triangle dans le modèle, faisant référence aux différents tampons d'attributs (position, couleur, coordonnées UV, autres coordonnées UV, normales…). C'est un peu comme dans le fichier .OBJ, avec une grande différence : il n'y a qu'un SEUL tampon d'indices. Cela signifie que pour qu'un sommet soit partagé entre deux triangles, tous les attributs doivent être les mêmes.

II - Partagé contre séparé

On va prendre en exemple les normales. Dans ce schéma, l'artiste qui a créé ces deux triangles voulait certainement qu'ils représentent une surface lisse. On peut donc fusionner les normales des deux triangles en une normale d'un seul sommet. Pour des soucis de visualisation, j'ai ajouté une ligne rouge qui représente l'aspect de la surface lisse.

Dans le second schéma, par contre, l'artiste a visiblement voulu une « couture », un côté pointu. Mais si on fusionne les normales, cela signifie que le shader va effectuer un adoucissement, comme d'habitude, et créer un aspect plus doux, comme avant :

Donc, dans ce cas il est préférable d'avoir deux normales distinctes, une pour chaque sommet. La seule façon de faire cela en OpenGL est de dupliquer entièrement le sommet, avec son ensemble d'attributs :

III - VBO indexé en OpenGL

Il est très simple d'utiliser l'indexation. Premièrement, vous devez créer un tampon supplémentaire, que vous allez remplir avec les bons indices. Le code est le même qu'avant, mais maintenant c'est un ELEMENT_ARRAY_BUFFER, et non un ARRAY_BUFFER.

std::vector<unsigned int> indices;

// Remplissez "indices" comme il faut

// Génère un tampon pour les indices
GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

Et pour dessiner le modèle, remplacez simplement glDrawArrays par :

// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

// Dessine les triangles
glDrawElements(
GL_TRIANGLES,      // mode
indices.size(),    // nombre
GL_UNSIGNED_INT,   // type
(void*)0           // décalage  du tableau de tampons
);

Il est préférable d'utiliser des « unsigned short » que des « unsigned int », car cela utilise moins de mémoire et accélère le programme.

IV - Remplir le tampon d'indices

On a maintenant un problème. Comme je l'ai dit avant, OpenGL ne peut utiliser qu'un seul tampon d'indices, alors que le format OBJ (ainsi que d'autres formats de fichier 3D populaires comme Collada) utilise un tampon d'indices par attribut. Cela signifie que d'une façon ou d'une autre, on doit convertir N tampons d'indices en un.

L'algorithme pour ce faire est le suivant :

Pour chaque sommet en entrée
Essayer de trouver un sommet similaire ( = identique pour tous les attributs) parmi ceux déjà en sortie
Si trouvé :
Un sommet similaire est déjà dans le VBO, utilisez le !
Si non trouvé :
Aucun sommet similaire trouvé, ajouter le au VBO

Le code C++ peut être trouvé dans le fichier common/vboindexer.cpp. Il est intensément commenté, donc si vous comprenez l'algorithme ci-dessus, cela devrait aller.

Le critère pour la similarité des sommets est que la position, la normale et les coordonnées UV doivent êtres identiques. Vous devez l'adapter si vous ajoutez plus d'attributs.

La recherche d'un sommet similaire est effectuée d'une manière linéaire pour garder l'algorithme simple. Une std::map serait plus appropriée.

V - Extra : le compteur de FPS

Ce n'est pas directement lié à l'indexation, mais c'est une bonne occasion de jeter un œil au compteur de FPS car on peut possiblement voir une amélioration de la vitesse grâce à l'indexation. D'autres outils pour les performances sont disponibles dans la page Outils - débogueurs.

VI - Remerciements

Cet article est une traduction autorisée dont le texte original peut être trouvé sur opengl-tutorial.org.

Navigation

Tutoriel précédent : shaders de base

Sommaire

Tutoriel suivant : latransparence