Navigation▲
Tutoriel précédent : shaders de base |
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 |
Tutoriel suivant : latransparence |