Bonjour tout le monde,
j'essaye de faire l'affichage de maillages triangulaire avec l'utilisation des VBOs pour des objet 3D assez gros (quelques dizaines de million de triangles) qui ont une structure assez proche des objets raffinés par le procédé de tesselation. En fait, j'ai des maillages avec une certaine quantité de triangles et je les subdivise avec une technique particulière qui fini par augmenter la quantité de triangle et par conséquent le détail de l'objet. Pour résumer, je subdivise un triangle dans n autres triangles. Les nouveaux triangles utilisent donc les sommets du triangle subdivisé, mais aussi de nouveaux points qui sont créés ainsi qu'une nouvelle topologie. Voila pour le résumé.
Pour l'affichage j'utilise les VBO, histoire de optimiser l'utilisation de la carte, évitant des transfert RAM -> VRAM inutiles comme on a avec le mode immédiat ou les vertex arrays ou les display listes. Alors, imaginons que j'ai un triangle dont les sommets sont donnés comme suit:
et topologie (indices):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 float SommetT1[] = { -0.5f,0.0f,0.5f, //S0 0.5f,0.0f,0.5f, //S1 0.0f,0.5f,0.5f //S2 };
Pour l'affichage je bufferise et dessine (en mode maille de fer) comme ça:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 uint IndicesT1[] = {0, 1, 2};
Bon, ça j'arrive à gérer sans souci. Le problème maintenant c'est d'afficher les nouveaux sous-triangles à la place de celui de base, sachant qu'ils utilisent les sommets de SommetT1[]. Imaginons que le triangle de base est subdivisé en 4 autres, avec donc les sommets en SommetT1 et des nouveaux comme suit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 //buffer des sommets int vboSommet1; glGenBuffers(1, &vboSommet1); glBindBuffer(GL_ARRAY_BUFFER, vboSommet1); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 3, SommetT1, GL_STATIC_DRAW); glVertexPointer(3, GL_FLOAT, 0, (char *) NULL); //buffer des indices int vboIndices1; glGenBuffers(1, vboIndices1); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndices1); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint) * 3 * 1, IndicesT1, GL_STATIC_DRAW); //dessin glEnableClientState(GL_VERTEX_ARRAY); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDrawElements(GL_TRIANGLES, 1 * 3, GL_UNSIGNED_INT, (char *) NULL); glDisableClientState(GL_VERTEX_ARRAY);
et avec la nouvelle topologie:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 float SommetT2[] = { 0.25f, 0.25f, 0.75f,//S3 -0.25f, 0.25f, 0.75f,//S4 0.00f, 0.00f, 0.75f //S5 };
avec les indices 0, 1 et 2 faisant référence aux sommets S0, S1 et S2 de SommetT1[] et les indices 3, 4 et 5 correspondant aux sommets S3, S4 et S5 de SommetT2[]. Bon, normalement si je veux afficher ces nouveaux triangles je dois recomposer un autre VBO avec une nouvelle liste de sommet comme ça:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 uint IndicesT2[] = { 3, 4, 5, 0, 5, 4, 1, 3, 5, 4, 3, 2 };
ce qui représente quand même un gaspillage d'utilisation de bande passante RAM -> VRAM puisque moité de ces sommets sont déjà dans un premier buffer dans la cg. Je pourrais utiliser la fonction glBufferSubData pour envoyer les sommets en SommetT2[] ce qui fait un grand buffer avec tout ce que j'ai bésoins sans renvoyer les sommets en SommetT1[]. Le problème là c'est que ce grand buffer je dois le créer avec la capacité totale pour accueillir les 6 sommets, ce que du coup représente un gaspillage de mémoire quand je ne veux afficher que le triangle de base. Pareil si je veux re-afficher les triangles de base après afficher les triangles détaillés (on ne peux pas faire de resize des VBO pur éliminé les sommet dont j'ai plus besoin. Puis, effacer tout le grand buffer et renvoyer les sommets de SommetT1 c'est le truc à éviter.)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 float SommetT1etT2[] = { -0.5f,0.0f,0.5f, //V0 0.5f,0.0f,0.5f, //V1 0.0f,0.5f,0.5f, //V2 0.25f, 0.25f, 0.75f,//V3 -0.25f, 0.25f, 0.75f,//V4 0.00f, 0.00f, 0.75f //V5 };
Voilà où j'en suis!Je vous appelle au secours
Est-ce qu'il y a un moyen d'éviter le renvoie des sommets de base mais qu'au même temps je puisse effacer les sommets des triangles détaillés une fois ne plus utilisé? Dans le cas ou j'ai plusieurs millions de sommet et quelques re-subdivisions à faire par triangle ça devient un grand problème qu'il faut gérer au risque de trop ralentir le rendu des objets (ou déborder la VRAM quand j'aurai à afficher plus d'un objet). Pour la topologie je dois renvoyer a chaque fois qu'on change de topologie (ou bien tout garder en VRAM quand possible!), mais ça on n'y peut rien.
Avez-vous des idée? Est-ce qu'il serait possible de fondre deux VBO et puis les re-séparer au besoin?D'ailleurs, comment openGL gère la tesselation, comment ils font pour optimiser la consommation de mémoire quand on change de niveau de détaille à répétition?
Merci à vous tous pour votre attention,
lao






Je vous appelle au secours
Répondre avec citation










Partager