Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1502 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Utilisation de Vertex Buffers

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

Utilisation de Vertex Buffers

n°1452386
Amonchakai
Posté le 04-10-2006 à 18:44:21  profilanswer
 

Bonjour !
   Dans le cadre d'un de mes projet je voudrais afficher une Mesh d'un object modelisé sous un éditeur 3D.  
Le truc c'est que me retrouve avec une série de vertices, de normales, et de coordonnées de texture et je voudrais tout afficher. Jusque la pas de problème : j'ai tout d'abord commencé par implémenter une méthode d'affichage via des l'utilisation de glDrawArray() (oui, par ce que je suis en openGL  ;) ). Mais on m'a fait remarquer que cette méthode n'était pas très "amicale" vis a vis du cache du GPU. Donc du coup je passe a l'utilisation de vertex buffer.  
Mais voilà, un petit coup de recherche Google et je tombe sur ça : http://www.g-truc.net/article/vbo-fr.pdf (le fait que celà soit en français n'était pas recherché. il se trouve que c'est en français, tant mieux...)
Et donc là j'ai quelques soucis :
   - tout d'abord ils n'ont pas l'air de de faire de déclarations de vertex... alors que j'aurrais pensé faire une structure du genre

Code :
  1. struct Vertex
  2. {
  3.    float u, v;
  4.    float nx, ny, nz;
  5.    float x, y, z;
  6. };


faire un vector de vertex et tout envoyer d'un coup...  
Disons que fait, tout en bas du document il parlent de la méthode glInterleavedArrays(GLenum format, GLsizei stride, GLvoid* pointer); qui a l'air de faire justement ça. MAIS ils disent qu'elle est obsolète.... Donc en gros pas à utiliser...  :(  
   - Ensuite ils ont l'air de recommender des glBufferSubData() pour remplir un buffer unique (créé avec glDataBuffer() ) pour stocker tous les vertex, puis toutes les normales, puis toutes les coordonnées de texture. Ce qui semble intéressant puisqu'ils affirment ensuite que je pourrais modifier le buffer partiellement... ce qui pourrais être intéressant pour les animations... Mais voilà ça me fait quitter le fait de tout envoyer d'un coup, ce qui était le but initial... Vous en pensez quoi ?
   - dernière question :) au sujet du stockage : je vois qu'après avoir tout affiché ils font un glDeleteBuffers(). heu, moi j'aurrais plutôt pas envis de détruire le buffer : ce qui est dans la mémoire de la carte graphique ne sera pas a renvoyer au prochain affichage... Bien sûr dans tous les cas je gardes mon vector de Vertex, mais si en plus je pourrais garder mon buffer, ça serait un gain de temp non ? Après j'imagine que c'est un compromis entre la vitesse et la mémoire de la carte graphique... Enfin votre avis m'intéresse :)
 
Voilà, Merci a ceux qui me répondront


Message édité par Amonchakai le 08-10-2006 à 10:46:59
mood
Publicité
Posté le 04-10-2006 à 18:44:21  profilanswer
 

n°1452402
_darkalt3_
Proctopathe
Posté le 04-10-2006 à 19:30:08  profilanswer
 

Est-ce que ca peut t'aider ?  
http://nehe.gamedev.net/data/lesso [...] ?lesson=45


---------------
Töp of the plöp
n°1452417
Amonchakai
Posté le 04-10-2006 à 20:13:35  profilanswer
 

Merci, pour le lien !  
Mais en fait, je connaissais. C'est a partir de NeHe que j'ai appris ce que je sais d'openGL...  :D  
 
- Bon par contre c'est vrai que c'est intéressant sur le fait du glDeleteBuffer() : il n'a pas l'air de l'utiliser après chaque affichage... Donc à priori, je peux me permettre dans une certaine mesure de conserver mes buffers.
- mais, il utilise encore une autre méthode (qui était décrite dans le document que j'avais trouvé...) qui consiste a utiliser deux buffer distinc pour l'affichage : un pour les vertices et un pour les coordonnées de textures. C'est toujours mieux qu'un array mais je pense que je vais essayer de regrouper au maximum mes donnée...
 
toujours est-il Merci de ta réponse !

n°1452420
_darkalt3_
Proctopathe
Posté le 04-10-2006 à 20:16:39  profilanswer
 

:jap:


---------------
Töp of the plöp
n°1452470
bjone
Insert booze to continue
Posté le 04-10-2006 à 21:39:20  profilanswer
 

le mieux est d'utiliser un indexbuffer (en plus):
 
http://www.blitzbasic.com/Communit [...] opic=47065
 
ça permet d'utiliser le cache post-T&L, et ainsi de reduire le nombre de vertexs a transformer par primitive.


Message édité par bjone le 04-10-2006 à 21:39:41
n°1452799
Amonchakai
Posté le 05-10-2006 à 14:28:39  profilanswer
 

Oui, c'est ce que je pensais faire.  
Donc la méthode que j'ai choisie, c'est de tout mettre dans un même buffer, en donnant les tableaux en trois fois. Puis pour l'affichage j'utilisearai un index buffer.
Donc en gros y'a plus qu'a... :D
 
Merci a tous !

n°1452839
bjone
Insert booze to continue
Posté le 05-10-2006 à 15:24:29  profilanswer
 

normalement c'est ce que développera un maximum d'efficacité.
 
idéalement, ré-organiser l'indexbuffer pour que les triangles fassent le plus de cache hit (très gros gains possibles), et défragmenter le vertexbuffer pour des accès le plus contigu possible (des pouillèmes de gains possible, surtout quand les gpu deviendront massivement MMU-isés pour rester dans la même page mémoire) .


Message édité par bjone le 05-10-2006 à 15:45:40
n°1452848
bjone
Insert booze to continue
Posté le 05-10-2006 à 15:37:32  profilanswer
 

là j'avais donné un exemple:
 
http://forum.hardware.fr/hardwaref [...] tm#t331004

n°1453036
Amonchakai
Posté le 05-10-2006 à 19:27:36  profilanswer
 

:ouch: hola c'est monstrueux (et maginfique...) comme méthode !  
 
Bon, par contre ce qui me fait un peu peur, c'est la complexité de ce type d'algorithme... Enfin du point de vue algorithmique, ça va pas me donner un algo de complexité exponentielle non ? enfin, je le sens comme ça... Même dans un temp de chargement ça risque d'être long. Va falloir que je crée un petit utilitaire pour "défragmenter" mes vertices, pour pouvoir les charger sans soucis après...
C'est quand même bizare que les éditeurs 3D ne le fasse pas  :??:  
 
preparez vous a me voir arriver avec mon algo de défragmentation qui marche pas  :D  
 
Sinon, je note la remarque que tu avait fait (il y a 3 ans...) de n'envoyer que les objects suceptible d'être affiché plutôt que tout envoyer a la carte graphique et de la laisser se demerder.
 
Allez a très bientôt :)

n°1453486
IrmatDen
Posté le 06-10-2006 à 16:33:01  profilanswer
 

Salut,
 
Si tu as quelques sous à dépenser et que le domaine du moteur 3D te botte vraiment, je te recommande chaudement la lecture de "3D Game Engine Design" de David Eberly. C'est "un peu" tendu niveau math (mais bon, je suis pas un bon, donc ceci explique cela :p ).
 
Il y explique tout ça, et le bouquin est accompagné d'un moteur 3D qu'il a développé, donc tu as tout le code nécessaire pour lire et apprendre comment le tout s'organise.
 
Il a aussi écrit 3D Game Engine Architecture qui vient en complément; par contre je ne l'ai pas encore acheté (mais ça va pas tarder ;) )

mood
Publicité
Posté le 06-10-2006 à 16:33:01  profilanswer
 

n°1453607
Amonchakai
Posté le 06-10-2006 à 18:30:57  profilanswer
 

Salut !
   Merci pour la réfernece du livre. Seul problème, c'est que je suis étudiant donc pas très riche. Et les 84$ du livre ça fait un peu trop pour moi pour l'instant. Mais je garde la référence pour pouvoir eventuellement me le prendre dans quelques mois...
 
Merci  :)

n°1453649
Amonchakai
Posté le 06-10-2006 à 22:03:51  profilanswer
 

Salut !
   Bon, j'ai un petit soucis avec mon implémentation d'un vertex buffer. Dans un premier temp je veut juste envoyer mes vertices sans index buffer (je l'ajouterais ensuite). Voilà la partie qui gère la mise des données dans le buffer :

Code :
  1. struct MeshToDisplay
  2. {
  3. std::vector<CVertex> VertexArray;
  4. std::vector<CTexCoord> TexArray;
  5. std::vector<CNormal> NormalArray;
  6. bool inBuffer;  //flag that indiquate that the mesh is store
  7. unsigned int buffer;
  8. };
  9. void OGLRender::StoreMesh(boost::shared_ptr<MeshToDisplay> ptr)
  10. {
  11. glGenBuffers(1, &ptr->buffer);    //we create a buffer
  12. glBindBuffer(GL_ARRAY_BUFFER, ptr->buffer); //we select the buffer
  13. glBufferData(GL_ARRAY_BUFFER, ptr->VertexArray.size() + ptr->NormalArray.size() + ptr->TexArray.size(), 0, GL_STREAM_DRAW);
  14. glBufferSubData(GL_ARRAY_BUFFER, 0, ptr->TexArray.size(), &ptr->TexArray[0]);  //we put the data
  15. glBufferSubData(GL_ARRAY_BUFFER, ptr->TexArray.size(), ptr->NormalArray.size(), &ptr->NormalArray[0]);
  16. glBufferSubData(GL_ARRAY_BUFFER, ptr->TexArray.size()+ptr->NormalArray.size(), ptr->VertexArray.size(), &ptr->VertexArray[0]);
  17. ptr->inBuffer=true;
  18. }


 
Bon le truc c'est qu'il plante dès l'appel de glGenBuffers() (ça ressemble beaucoup a problème de pointeur comme crash). Je suis sûr que le pointeur ptr est valide. Car j'ai put tester qu'il y a bien les coordonnées de  mes vertices dans le pointeur. Donc sur le coup je ne vois pas d'où celà viens. Vous avez une idée ?
 
Merci :)

n°1453800
Amonchakai
Posté le 07-10-2006 à 14:49:28  profilanswer
 

Salut !
 
   J'ai même essayé de simplifier encore plus mon code et rien que ça, ça ne marche pas :
 

Code :
  1. static GLuint buffer;
  2. MessageBox(NULL, "Passe 0", "passe", MB_OK);
  3. glGenBuffers(1, &buffer);
  4. MessageBox(NULL, "Passe 1", "passe", MB_OK);
  5. float vertexTab[] = {
  6. -1.0f,-1.0f, -1.0f,
  7.  1.0f,-1.0f, -1.0f,
  8.  1.0f, 1.0f, -1.0f,
  9.  1.0f, 1.0f, -1.0f,
  10. -1.0f, 1.0f, -1.0f,
  11. -1.0f,-1.0f, -1.0f};
  12. glBindBuffer(GL_ARRAY_BUFFER, buffer);
  13. glBufferSubData(GL_ARRAY_BUFFER, 0, 18*sizeof(float), vertexTab);


 
j'ai la MessageBox() qui me dit passe 0 et ensuite visual just in time debugger se lance et me dit "an unhandled win32 exception occured in _Xero_.exe " et ensuite le programme s'arrête. J'ai essayé de mettre le glGenBuffers() dans un bloc try pour essayer d'avoir l'erreur mais j'ai rien récupéré. Vous auriez une idée ?
 
Merci :)


Message édité par Amonchakai le 07-10-2006 à 14:50:09
n°1453861
Amonchakai
Posté le 07-10-2006 à 19:17:54  profilanswer
 

Bon, j'ai finalement réussit !
Donc l'histoire, c'est que j'avais voulut utiliser une librairie applelée glew qui définissait d'elle même les vertex buffer. Et là je sais pas pourquoi ça ne marche pas. Donc j'ai du laisser tomber ma méthode de faignant et récupérer mes différentes méthodes via des wglGetProcAddress()... Et là comme ça ça marche impécable :)
 
prochaine étape : les index buffer  :)  

n°1453882
bjone
Insert booze to continue
Posté le 07-10-2006 à 20:36:56  profilanswer
 

pourquoi tu stoques pas tout dans une seule structure et via un seul vector<> ?

n°1453889
Amonchakai
Posté le 07-10-2006 à 21:18:59  profilanswer
 

Ben, par ce que j'ai lu que la méthode qui permet de faire celà est  

Code :
  1. glInterleavedArrays(GLenum format, GLsizei stride, GLvoid* pointer);


Mais ils disent également qu'elle est obsolète... et qu'il vaut mieux utiliser les tableaux entrelacés. Mais après si tu dit que c'est mieux, je le fait, y a pas de soucis...

n°1453891
Amonchakai
Posté le 07-10-2006 à 21:28:33  profilanswer
 

et ils disent également que cette méthode est inadaptée aux rendus utilisant du multitexturing et des shaders...

n°1453916
Amonchakai
Posté le 08-10-2006 à 10:46:15  profilanswer
 

Bonjour !
 
   Bon, je suis en train de regarder comment je peut utiliser le glInterleavedArrays(). Mais j'ai un proglème : je vois pas comment on l'utilise. Je suis allé voir sur MSDN. là j'ai crut comprendre qu'il fallait que je fasse ça :

Code :
  1. glBufferDataARB(GL_ARRAY_BUFFER, ptr->Data.size()*8*sizeof(float),  &ptr->Data[0], GL_STATIC_DRAW);
  2. glInterleavedArrays(GL_T2F_N3F_V3F, 0, 0);


avec Data un vector de Vertex. (Vertex étant la structure dont j'ai parlé dans mon prmier post...)
 
Et donc  

Code :
  1. glInterleavedArrays(GL_T2F_N3F_V3F, 0,0);


remplace

Code :
  1. glTexCoordPointer(2, GL_FLOAT, 0, 0);
  2. glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(ptr->TexArray.size()));
  3. glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(ptr->TexArray.size()+ptr->NormalArray.size())); //select data in the memory  
  4. glEnableClientState(GL_VERTEX_ARRAY);
  5. glEnableClientState(GL_NORMAL_ARRAY);
  6. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  7. glDrawArrays(GL_TRIANGLES, 0, ptr->VertexArray.size());  //display
  8. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  9. glDisableClientState(GL_NORMAL_ARRAY);
  10. glDisableClientState(GL_VERTEX_ARRAY);


 
c'est bien ça ? Si oui, j'ai un soucis car ça ne marche pas...
 
Merci :)


Message édité par Amonchakai le 08-10-2006 à 12:59:26
n°1458461
bjone
Insert booze to continue
Posté le 17-10-2006 à 02:17:40  profilanswer
 

Amonchakai a écrit :

Ben, par ce que j'ai lu que la méthode qui permet de faire celà est  

Code :
  1. glInterleavedArrays(GLenum format, GLsizei stride, GLvoid* pointer);


Mais ils disent également qu'elle est obsolète... et qu'il vaut mieux utiliser les tableaux entrelacés. Mais après si tu dit que c'est mieux, je le fait, y a pas de soucis...


 
je sais pas trop ce que vaux cette façon de faire, et je sais pas si ça correspond à ce que je pense.
ça me semble liés aux Arrays d'OpenGl 1.1 ou un truc du genre, et pas aux VBOs.
 
a priori je pense qu'il faut plus faire un:
 
glBindBufferARB(
glVertexPointer(
glTexCoordPointer(
...
avec les bons strides & offsets.

n°1458462
bjone
Insert booze to continue
Posté le 17-10-2006 à 02:19:22  profilanswer
 

mais j'avoues là, je sais pas quel est le bon séquencement grâce à la coexistance des Arrays classiques et des VBOs.

n°1459048
Amonchakai
Posté le 17-10-2006 à 18:21:22  profilanswer
 

Salut !
   Ha d'accord, je viens enfin de comprendre ce que tu veut dire...
   Oui, par ce que j'avais en tête ce que j'avais vu sur directX (bon de très loin car je ne sais pas utiliser DirectX actuellement...) et j'avais compris qu'il fallait déclarer la structure des données qu'il fallait envoyer, et qu'il existait des flags qui permetait de spécifier le format utilisé. Ce que j'ai donc cherché à retrouver en openGL, d'où le glInterleavedArrays().
   
   Toujours est-il que maintenant je vois bien le truc. je vais mettre ça a jour :)
 
Merci


Message édité par Amonchakai le 17-10-2006 à 18:22:11
n°1459740
bjone
Insert booze to continue
Posté le 18-10-2006 à 16:14:58  profilanswer
 

oki
 
effectivement, sous Direct3D 9, il existe aussi un peu une co-existance un peu comme les Arrays et les VBOs de l'OpenGl, au niveau de la déclaration des VertexBuffers:
 
Tu as une fonction SetFVF() qui est un héritage du T&L fixe datant de D3D 7 (je crois car j'ai pas connu heureusement :D), ou tu déclares le format des données par Vertex avec des combinaisons de flags.
 
Et maintenant avec D3D9 (ou depuis le 8 je sais plus :lol:), tu as un truc pour déclarer le format du Vertex bien plus adapté aux Vertexs & Pixels Shaders dans lequel tu passes un tableau d'eléments déclarant bien plus précisément la nature d'un élément du Vertex:
taille, offset dans le vertex, nature "simple" (position, normale, valeur quelconque...), et la manière de faire la tessellation si la géométrie doit passer par un tessellateur.  
 
D3D10 dégagant les restes du T&L fixe a grands coups de shotgun, ce qu'il fait qu'il ne restera plus que l'approche utilisant une description plus précise de la structure d'un Vertex.


Message édité par bjone le 18-10-2006 à 16:16:31
n°1460089
Amonchakai
Posté le 18-10-2006 à 22:06:22  profilanswer
 

Merci pour l'explication !
 
Je regarderais ça plus en détail quand je m'occuperai de l'implémentation DirectX pour le moment j'ai déja bien à faire avec openGL.
 
(Je me suis mis à l'algo de "défragmentation" de vertex. et j'ai quelques petit soucis... je le posterai quand je l'aurrai fini :) )
 
Salutation !

n°1460170
bjone
Insert booze to continue
Posté le 19-10-2006 à 00:01:05  profilanswer
 

alors attention: bien que ce soit utilie, il est -BIEN- plus important de réorganiser les triangles, dumoins leurs indexes pour bien utiliser le cache Post-T&L.
 
Personnellement je suis parti de nvStrip de nVidia pour faire mon propre réorganiseur de triangle.
 
ce qu'il faut comprendre, pour maximiser le rendement:
les strips c'est bien mais:
des strips indépendants (rafales de quelques dizaines de triangles) c'est mal car ça génère des petits batches (trop de commandes de traçages OpenGl ou D3D)
il faut donc générer des strips dits "dégénérés" ou tu places un vrai-faux triangle dont deux sommets sont à un indice identique, le triangle sera neutralisé par le culling, et ça permet des connecter des strips géométriquement indépendants afin de faire toute la géométrie (a matériau identique) en une commande.
 
perso j'ai joué avec ça, et j'ai fini par faire des triangles indépendants optimisés pour le cache Post-T&L.
 
donc en compromis tu as:
 
- strips isolés: trop de commandes de traçage
 
- strips dégénérés: "vrai-faux" triangles pour connecter des strips isolés, si les strip sont trop "courts", le pourcentage de "vrai-faux" triangles peut faire perdre en rendement.
 
- triangles indépendants: triangles et commandes de traçage minimales,  consomme un peu plus de bande-passante mémoire dans l'absolu pour "fetcher" les indices (3 indices 16bits ou 32bits par triangle au lieu de 1 indice dans le cas d'un strip)..... mais l'ordre de grandeur est ridicule en comparaison aux vertexs eux-mêmes et aux accès texture.
 
généralement tu est gagnant (attention c'est mon avis perso) avec les triangles indépendants étant donné qu'en bonus c'est beaucoup plus d'actualiser la géométrie procéduralement (ie dégager ou insérer des triangles à la volée dans une géométrie stripifiée est potentiellement pête-couilles, alors qu'avec des triangles indépendants c'est assez trivial)
 
--
 
en fait moi je fais tout cette optimisation dans mon exporteur 3DSMax..
 
je fait une optimisation du flux de triangles indépendants par brute-force :
je simule le cache Post-T&L (par exemple une Geforce 1 qui a utilise un cache FIFO de 12 entrées), pour chaque vertex je maintiens la liste des triangles qui l'utilise, et partant du premier triangle de mon lot de triangles, je cherche le triangle suivant non déjà émis qui procurera le plus de "cache-hit".
 
ie j'ai le premier triangle dont les sommets sonts 12 32 789:
 
j'ai auparavant stoqué par vertex quel triangles étaient utilisés.
 
ça me donne un cache FIFO comme ça:
 
12 32 78 X X X X X..... (X pour rien de caché, jusqu'aux 12 ou+ vertexs cachés)
 
et ensuite pour chercher le prochain triangle a emettre, je regarde pour quel est l'élu qui me donnera le plus de cache-hit vis à vis du cache FIFO.  
une fois que je l'ai, je l'émets dans un buffer, et j'actualise le cache FIFO en y poussant les vertexs non cachés tu triangles émis.
 
et comme ça je construit une bonne séquence de triangles (pas forcément la meilleure dans l'absolu).
 
ce qui peut donner: (* cache hit | état cache FIFO)
12 32 78  * 0 | 12 32 78 X X X X.....
12 32 85  * 2 | 85 12 32 78 X X X X.....
12 78 56  * 2 | 56 85 12 32 78 X X X X...
78 85 56  * 3 | 56 85 12 32 78 X X X X....
 
une fois que un as un flux de triangles bien-bien, tu peux commençer à défragmenter et réindexer les vertexs pour avoir des accès mémoires optimaux.
 
---
 
Pourquoi me baser sur une Geforce 1 (ou 2 ché pu je m'étais baser sur les infos de nvStrip) pour le cache Post-T&L ?  
 
=> Parceque en termes de cache, il vaux mieux se baser sur le plus petit "connu", ie même si sur une carte moderne (genre Geforce 7 ou Radeon X1900) tu as un cache bien plus efficace genre (pseudo-)LRU 32/64/1024 entrées (j'imagines totalement là je sais pas du tout où en est), les performances seront quand même largement correctes, alors que si tu optimises pour un cache excellent alors que t'as un ptit truc, tu va cache-trasher à mort. (c'est pareil pour un CPU, si tu bosses dans un buffer 16Ko alors que ton CPU a 4Ko de L1 ça va trasher en dehors du L1, alors que si bosses avec un buffer 4Ko, et même si ton CPU a un cache 16Ko de L1, les perfs seront quand même excellentes).

n°1460171
bjone
Insert booze to continue
Posté le 19-10-2006 à 00:05:51  profilanswer
 

et on est bien d'accord que l'export de la géométrie depuis 3DSMax mets des "plombes" (ie une poignée de seconde, 4/5secs grand max pour un modèle conséquent, genre l'Apollo de base fourni en exemple)
 
donc c'est clairement quelque chose à faire en hors-ligne (hors moteur 3D temps-réel).

n°1460176
bjone
Insert booze to continue
Posté le 19-10-2006 à 00:25:06  profilanswer
 

mais bon avant de te prendre la tête avec ça, fait que ton code OpenGl utilise correctement les VBOs et ce qui fait office d'IndexBuffer.

n°1460947
Amonchakai
Posté le 19-10-2006 à 21:03:51  profilanswer
 

j'ai justement fini mon implémentation des vertex Buffer utilisant un index Buffer : :D
 

Code :
  1. struct CVertex
  2. {
  3. float u, v,
  4.    nx, ny, nz,
  5.    x, y, z;
  6. };
  7. struct MeshToDisplay
  8. {
  9. std::vector<CVertex> data;
  10. std::vector<unsigned int> index;
  11. bool inBuffer;
  12. unsigned int buffer;
  13. unsigned int indexBuffer;
  14. };
  15. void OGLRender::StoreMesh(boost::shared_ptr<MeshToDisplay> ptr)
  16. {
  17. ptr->buffer = NULL;
  18.     ptr->buffer = NULL;
  19. glGenBuffersARB(1, &ptr->buffer);    //we create a buffer
  20. glGenBuffersARB(1, &ptr->indexBuffer);
  21. glBindBufferARB(GL_ARRAY_BUFFER, ptr->buffer); //we select the buffer
  22. glBufferDataARB(GL_ARRAY_BUFFER_ARB, (8*ptr->data.size())*sizeof(float), &ptr->data[0], GL_STATIC_DRAW); //we store the data
  23. glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ptr->indexBuffer);
  24. glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, ptr->index.size()*sizeof(unsigned int), &ptr->index[0], GL_STATIC_DRAW);
  25. ptr->inBuffer=true;
  26. }
  27. void OGLRender::PaintMesh(boost::shared_ptr<MeshToDisplay> ptr)
  28. {
  29. if(!ptr->inBuffer)
  30.  return;
  31. glBindBufferARB(GL_ARRAY_BUFFER, ptr->buffer);
  32. glTexCoordPointer(2, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(0));
  33. glNormalPointer(GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(2*sizeof(float)));
  34. glVertexPointer(3, GL_FLOAT, 8*sizeof(float), BUFFER_OFFSET(5*sizeof(float)));
  35. glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, ptr->indexBuffer);
  36. glEnableClientState(GL_VERTEX_ARRAY);
  37. glEnableClientState(GL_NORMAL_ARRAY);
  38. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  39. glDrawElements(GL_TRIANGLES, ptr->index.size(), GL_UNSIGNED_INT, 0);  //display
  40. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  41. glDisableClientState(GL_NORMAL_ARRAY);
  42. glDisableClientState(GL_VERTEX_ARRAY);
  43. }
  44. void OGLRender::ReleaseMesh(boost::shared_ptr<MeshToDisplay> ptr)
  45. {
  46. glDeleteBuffersARB(1, &ptr->buffer);
  47. glDeleteBuffersARB(1, &ptr->indexBuffer);
  48. ptr->inBuffer=false;
  49. }


 
Et ça marche :)
Bon étape suivante : la réorganisation des triangles...


Message édité par Amonchakai le 19-10-2006 à 21:14:55
n°1461021
bjone
Insert booze to continue
Posté le 19-10-2006 à 23:40:04  profilanswer
 

niquel, 2/3 petites remarques:
 
il vaut mieux mettre la position en premier dans le vertex. (idéalement dans un VertexShader il faut "sortir" la position transformée le plus tôt possible, donc dans le doute question latence ça peut être mieux).
 
tu peux grapiller un peu de bande-passante et de conso mémoire en utilisant des shorts pour l'IndexBuffer.
 
remarque de design objet:
tu as déporté le code OpenGl vers OGLRender, mais tu stoques des handles "propres" à OpenGl dans MeshToDisplay (buffer, indexbuffer).
si tu veux vrairement faire "abstraction" de l'api 3D il faudrait trouver un moyen de masquer ces buffer, indexbuffer via une classe interface, ptet style:
 
class RendererHandles
{
 public:
   virtual ~RendererHandles() = 0;
};  
 
class MeshToDisplay
{
public:
   std::vector<CVertex> data;
   std::vector<unsigned int> index;
   smart_ptr<RendererHandles> Handles;
};
 
class OGLHandles : public RenderHandles
{
public:
    bool inBuffer;    
    unsigned int buffer;
    unsigned int indexBuffer;
 
    ...
};
 
et grâce au destructeur tu libères les buffers OpenGl.
 
bon ça c'est plus une remarque de principe, hein dans un premier temps je te conseillerais de rester uniquement en OpenGl et pas a chercher a faire une abstraction de l'API 3D.

n°1461052
Amonchakai
Posté le 20-10-2006 à 06:47:29  profilanswer
 

oki, je vais corriger ces petites choses...  
 
Merci :)

n°1461628
Amonchakai
Posté le 20-10-2006 à 19:15:05  profilanswer
 

De retour, avec la première partie de mon algo : la réorganisation des triangles

Code :
  1. #define FIFOSIZE 12
  2. struct Triangle
  3. {
  4. int vertex[3];
  5. };
  6. void swap(Triangle &tri1, Triangle &tri2)  //swap two Triangles
  7. {
  8. int temp;
  9. temp = tri1.vertex[0];
  10. tri1.vertex[0] = tri2.vertex[0];
  11. tri2.vertex[0] = temp;
  12. temp = tri1.vertex[1];
  13. tri1.vertex[1] = tri2.vertex[1];
  14. tri2.vertex[1] = temp;
  15. temp = tri1.vertex[2];
  16. tri1.vertex[2] = tri2.vertex[2];
  17. tri2.vertex[2] = temp;
  18. }
  19. // ************programme de réorganisation des triangles*************
  20.     std::vector<Triangle> triangleArray;
  21. std::vector<int> cacheFIFO;
  22. cacheFIFO.push_back(triangleArray.at(0).vertex[0]);       //the 3 first vertex of the cacheFIFO
  23. cacheFIFO.push_back(triangleArray.at(0).vertex[1]);
  24. cacheFIFO.push_back(triangleArray.at(0).vertex[2]);
  25. for(unsigned int n = 1 ; n < triangleArray.size()-1 ; n++)     //we look for all triangle.
  26. {
  27.  int index_cache_hit = 0;            //store the index of the max cache hit
  28.  int max_cache_hit = 0;             //value of the max cache hit
  29.  for(unsigned int i = n ; i < triangleArray.size() ; i++)    //we look all the others triangles
  30.  {
  31.   int cache_hit = 0;
  32.   for(int j = 0 ; j < 3 ; j++)
  33.    for(unsigned int k = 0 ; k < cacheFIFO.size() ; k++)
  34.     if(triangleArray.at(i).vertex[j] == cacheFIFO.at(k))
  35.      cache_hit++;           //we count the number of cache hit
  36.   if(cache_hit>max_cache_hit)
  37.   {
  38.    max_cache_hit = cache_hit;
  39.    index_cache_hit = i;
  40.   }
  41.  }
  42.  for(int i = 0 ; i < (3-max_cache_hit) ; i++)
  43.  {
  44.   for(int k = 0 ; k < 3 ; k++)
  45.   {
  46.    bool here = false;
  47.    for(unsigned int j = 0 ; j < cacheFIFO.size() ; j++)
  48.     if(triangleArray.at(index_cache_hit).vertex[k] == cacheFIFO.at(j)) //we search witch one is new
  49.     {
  50.      here = true;
  51.      break;
  52.     }
  53.    if(!here)
  54.     cacheFIFO.push_back(triangleArray.at(index_cache_hit).vertex[k]); //we put the new vertices in the cacheFIFO
  55.   }
  56.  }
  57.  swap(triangleArray.at(n), triangleArray.at(index_cache_hit));
  58.  while(cacheFIFO.size() > FIFOSIZE)
  59.   cacheFIFO.erase(cacheFIFO.begin());
  60. }


 
Et ça a l'air de bien marcher :)
Ca te parait correct ?
 
reste plus qu'a réorganiser les indices des vertices...
 
[edit] j'ai retiré 2-3 commentaires pour pas trop foutre en l'air la mise en page du forum... :D


Message édité par Amonchakai le 20-10-2006 à 19:18:35
n°1461675
bjone
Insert booze to continue
Posté le 20-10-2006 à 20:43:32  profilanswer
 

a première vue ça a l'air correct.

n°1462060
Amonchakai
Posté le 21-10-2006 à 17:53:56  profilanswer
 

Salut !
   heu, bjone ton exporteur mettait vraiment 4/5 s pour exporter un modèle .3ds ?
   par ce que pour le moment le mien il met..... 25s pour un modèle de seulement 8000 triangles  :whistle:  
 
   Je pense qu'il y a un gros boulôt d'optimisation à faire... :)

n°1462150
Amonchakai
Posté le 21-10-2006 à 19:48:49  profilanswer
 

En fait, ça viens peut-être que 8000 triangles c'est énorme... Je viens de revoir le personnage que j'avais modélisé sous milkshape3D et il fait 900 Triangles, et son exportation va plutôt vite... (j'ai pas le temp de le chronométrer a la montre...) Donc en fait, j'ai quand même fait une petite optimisation : quand j'ai un cache hit de 3 c'est pas la peine d'aller chercher plus loin... Et ça marche plutôt bien.
 
Salutation !

n°1462152
bjone
Insert booze to continue
Posté le 21-10-2006 à 19:53:36  profilanswer
 

bin heu j'ai un Nostromo de 300000 triangles :D
attends je benches :D

n°1462155
bjone
Insert booze to continue
Posté le 21-10-2006 à 20:17:24  profilanswer
 

Bon ça fait 15 secondes pour 300K triangles :D
(mais bon C2D à 3.4Ghz :D)
 
http://img332.imageshack.us/img332 [...] omowv4.png
 
ça tiens à 200fps sur ma X1900XTX:
 
http://img326.imageshack.us/img326 [...] orthz1.jpg
 
t'inquiètes pas c'est pas moi qui est modélisé le biniou, je l'ai pris sur un site de modèle 3DS (d'ailleurs il était ils construit n'importen'awaquement avec 10000 nodes de 30 triangles)


Message édité par bjone le 21-10-2006 à 20:19:49
n°1462186
Amonchakai
Posté le 21-10-2006 à 21:27:20  profilanswer
 

Et bien franchement il est tout simplement magnifique !
Et félicitation pour avoir réussit a l'afficher avec un 200fps... (au passage ça a l'air sympa ce que tu fait :) )
 
bon moi avec mon modeste unique CPU Athlon64 3400+ et bien je met 7min 15s pour... 17500 triangles.  :cry:  (Milkshape veut pas comprendre que ça existe des models de plus de 17500 triangles...). Je sais pas comment tu l'a fait, mais je crois que sans multithreading ça sert a rien d'avoir plusieurs CPU... Donc la lenteur de mon programme, ça doit venir de mon algo. Je vais voir si j'arrive a l'améliorer. Au pire a mon échelle (de 1000 triangles) ça reste acceptable.

n°1462298
bjone
Insert booze to continue
Posté le 22-10-2006 à 02:26:06  profilanswer
 

pour accélérer la réorganisation, tu peux maintenir, pour chaque triangle, ses triangles adjacents sur chaqun de ces cotés. et dans le cache FIFO maintenir par entrée de cache quel triangle utilisait l'entrée (en plus de l'indice).
 
comme ça tu peux trouver très rapidement si un triangle adjacent fait un gros cache hit.
 
perso au lieu d'échanger un triangle, je maintiens une table de remapping (genre avec un -1 pour dire non re-mappé), ce qui permet de maintenir la cohérence avec les tables de triangles adjacents.
 
de plus les tables de triangles adjacent peut être aussi utile lors de génération de decals qui suivent la géométrie du mesh. (impacts de projectiles/éraflures)

n°1468483
Amonchakai
Posté le 31-10-2006 à 21:32:40  profilanswer
 

Kikou !
   Bon, je réssucite mon topic juste pour dire que j'ai retouché a mon algo et maintenant je fais 9s pour 175 000 triangles  :sol:  
 
   Merci a toi bjone pour tes conseils avisés dans l'optimisation de mon programme...   :)


Message édité par Amonchakai le 31-10-2006 à 21:48:27
n°1468542
bjone
Insert booze to continue
Posté le 01-11-2006 à 01:57:40  profilanswer
 

y'a certainement d'autres trucs à dire, mais vérifies le framerate avec un très gros modèle voir si tu touches bien les limites des perfs géométriques de ta carte.

n°1468561
Amonchakai
Posté le 01-11-2006 à 09:20:03  profilanswer
 

oki, je vais regarder

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Utilisation de Vertex Buffers

 

Sujets relatifs
HELP Utilisation de microphone.get() ??pb d'utilisation de fseek
Win Api : L'utilisation du menu fait planter le programmeUtilisation de sed
chercher exemple simple d'utilisation de ComboBox()Utilisation de WM_PAINT
[help me] utilisation d un graph (graphedit)Batch - Erreur d'utilisation de la commande ncftpget
Utilisation D une variable dans un lien[Java] Problème de conception par rapport à l'utilisation d'une BD
Plus de sujets relatifs à : Utilisation de Vertex Buffers


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR