Quelle structure pour un jeu en 3D ? - C++ - Programmation
Marsh Posté le 26-03-2004 à 14:35:54
déjà trouvé le vecteur normal d'une face pas plane c'est assez chaud ...
Sinon moi aussi j'y avais réfléchis et faire plustot un système de template:
face<n>.display();
Me semblais une bonne idée.
Marsh Posté le 26-03-2004 à 14:44:39
ben nan, paske imagine que t'as des faces avec des nombres de sommets allant de 3 à 18 avec tous les itermédiaires, ça va rien arrangé, de faire une class template. sans compter que ça règle pas le problème de tester la valeur de n... ou alors je vois pas ce que tu veux dire. et sinon, pour les faces pas planes, on peut éventuellement bidouiller, pour la normale, en prenant une normale différente pour chaque sommet, voir tout un tas de normales différentes sur toute la surface (j'ai déjà fais un truc dans le genre dans le cas d'un terrain fais à partir d'une heightmap, même si c t pas forcément une bonne idée).
enfin bref, si tu pouvais détailler ton histoire de template...
Marsh Posté le 26-03-2004 à 14:49:32
euh sinon, autre question : quand on affiche une sphere en OpenGL (en utilisant les objets quadratiques), si on veux l'afficher avec de la transparence, on le "derrière" de la sphère aussi, à travers le "devant" ? parce que sinon, je vais pas me lancer dans l'utilisation des objets quadratiques, vu que j'ai jamais fais ça... (le but de la manoeuvre est d'afficher un bouclier autour d'un vaisseau, une sphère translucide, donc, avec une texture, bien sûr).
Marsh Posté le 26-03-2004 à 14:50:04
toute ta géométrie est en triangle.
au traçage, tu traçes par paquer de 1000+ triangle par appel.
tu as deux jeux de géométrie, une adapté à la carte 3D, l'autre à tes tests de collision.
règle de base:
NE JAMAIS FAIRE D'APPEL DE FONCTION D'API GRAPHIQUE PAR PRIMITIVE
sinon tu seras à 0.01% de rendement de ta carte 3D.
pour maximiser les performances, il faut:
1) minimiser la charge de la scène: la carte 3D rejette les surfaces hors-frustum, mais tu dois tester en amont ce qui est dans le champ de vision (au niveau objet par boite englobante ou autre, hors de question de tester au niveau triangle au niveau CPU)
2) minimizer les changements d'états
3) avoir un maximum de triangles traçés par appel de primitive de l'API (en OpengGl compiler une séquence de traçage, utiliser des vertex arrays/vertex buffer object, en DirectX vertexbuffer/indexbuffer/drawprimitveindex)
techniquement les ressources géométriques seront très probablement mises en ram vidéo par l'api.
le cpu accède très lentement aux ressources graphique, le gpu accède très lentement aux ressources du cpu. (d'où l'histoire des deux jeux de ressources structurées différement du début du post)
Marsh Posté le 26-03-2004 à 14:50:34
euh dans mon message précédent, je voulais dire "on voit le derrière", j'ai oublié un mot...
Marsh Posté le 26-03-2004 à 14:52:47
si tu vois le derrière, et que tu veux pas, c'est que tu as un problème de (backface) culling.
Marsh Posté le 26-03-2004 à 14:53:34
quand tu dis de compiler une séquence de traçage, tu veux dire utiliser une liste ? et en fait, je sais pas comment marchent les vertex arrays, mais j'étais tombé dessus en trainant une doc openGL, et je comptais voir ça de plus près...
Marsh Posté le 26-03-2004 à 14:54:07
bjone, erf, ok, j'avais pas pensé au culling. mais je veux voir le derrière, justement. merci.
Marsh Posté le 26-03-2004 à 14:58:00
par contre, le coup des deux jeux de géométrie, tu veux dire qu'il faut que j'ai un seul gros tableau de triangles pour dessiner, et à coté des objets organisé comme je veux pour tout ce qui n'est pas dessin ? et que avant de dessiner je synchronise mon tableau de triangles en fonction des objets qui ont bougé ?
Marsh Posté le 26-03-2004 à 14:58:32
oui scuze.
je code en DirectX, qui expose essentiellement l'implémentation moderne des cartes 3D.
le prob avec l'OpenGl, c'est qu'il expose des approches obsolètes en rendement, donc fo fuir un maximum les glvertex, et les glbegin() par primitive. (si y'a pas une utilisation de fonctions de compactage/optimisation derrière)
Marsh Posté le 26-03-2004 à 15:01:35
ok, merci du conseil, c justement comme ça que je faisais jusque là, en dessinant par primitive (vu que le premier exemple que j'ai vu en OpenGL faisait comme ça, n'y connaissant rien, j'ai suivi...) et justement, au vu des performances minables, je me suis dis que ça devait pas être la bonne méthode, et je cherchais autre chose... donc de toute façon je pense que c'est ce que j'aurais fais, mais là au moins je suis sûr
Marsh Posté le 26-03-2004 à 15:03:37
Yawen a écrit : par contre, le coup des deux jeux de géométrie, tu veux dire qu'il faut que j'ai un seul gros tableau de triangles pour dessiner, et à coté des objets organisé comme je veux pour tout ce qui n'est pas dessin ? et que avant de dessiner je synchronise mon tableau de triangles en fonction des objets qui ont bougé ? |
spa ça.
mais prenons le fuselage d'un avion.
si tu veux faire des tests triangles / rayon, pour tester l'impact d'une balle sur le fuselage.
le mieux en perfs, c'est d'avoir un "objet" OpenGl qui contienne la géométrie du fuselage, qui permette le traçage le plus rapide possible. et d'avoir aussi un "objet" structuré maison qui permette de calculer l'intersection triangle/rayon le plus rapidement possible.
chercher le compromis d'une structure qui te permettes de fournir le meilleur rendement OpenGl vis à vis de la carte 3D, et d'avoir le meilleur rendement pour le test d'intersection est généralement bancal et délivrera un rendement pourri pour les deux. (bien sûr tu as des exceptions... )
après, quand tu as obtenu le point d'intersection, rien ne t'empêche d'actualiser une portion de "l'objet OpenGl".
Marsh Posté le 26-03-2004 à 15:04:18
et justement, juste pour savoir, si je dessine par primitive dans une liste, et que après j'apelle la liste, ça veut dire que l'API aura tout optimisé à ma place ? et dans ce cas est ce que c'est jouable de changer les matrices de translation rotation chaque fois qu'on dessine une liste (représentant un solide complexe) pour l'afficher à la bonne position ? enfin en gros, dans le cas d'un jeu avec des vaisseaux dans l'espace, si je fais une liste par vaisseau et que je bidouille les matrices avant d'afficher chaque vaisseau, c bon ?
Marsh Posté le 26-03-2004 à 15:06:08
"le mieux en perfs, c'est d'avoir un "objet" OpenGl qui contienne la géométrie du fuselage"
euh ben mon "objet openGL", il doit être fais comment pour être optimal, alors ? (en imaginant que y'ai que des faces triangulaires)
Marsh Posté le 26-03-2004 à 15:08:46
Yawen a écrit : et justement, juste pour savoir, si je dessine par primitive dans une liste, et que après j'apelle la liste, ça veut dire que l'API aura tout optimisé à ma place ? et dans ce cas est ce que c'est jouable de changer les matrices de translation rotation chaque fois qu'on dessine une liste (représentant un solide complexe) pour l'afficher à la bonne position ? enfin en gros, dans le cas d'un jeu avec des vaisseaux dans l'espace, si je fais une liste par vaisseau et que je bidouille les matrices avant d'afficher chaque vaisseau, c bon ? |
exactement.
l'idée générale c'est:
t'as ta classe model/mesh:
-> tes vertexs
-> changement d'états
-> ta liste de traçage
ta classe entitée:
-> matrice de position monde
-> autres états (physique/ia....)
-> pointeur sur classe model/mesh
au traçage:
pour chaque entitée
matrice_de_monde = entitée->matrice de monde
tracer( entitée->modèle )
Marsh Posté le 26-03-2004 à 15:12:20
ok, merci, je vais étudier la question... euh par contre, pour en revenir à mon problème de départ, le coup des classes héritées pour avoir différent types de faces dans un même tableau, c une bonne idée ou pas ? (évidemment, je sais pas, du coup, si j'utiliserais la technique pour des faces, mais il se trouve que dans mon programme précédent, je faisais ça aussi pour les sons, les vaisseaux, les projectils, etc...)
Marsh Posté le 26-03-2004 à 15:13:03
Yawen a écrit : "le mieux en perfs, c'est d'avoir un "objet" OpenGl qui contienne la géométrie du fuselage" |
j'ai pas trop regardé en OpenGl, mais ça devrait être tout ce qui est Vertex Array
http://prografix.games-creators.org/document/122
(coup de google vite fait)
et Vertex Buffer Object
Marsh Posté le 26-03-2004 à 15:18:12
Yawen a écrit : ok, merci, je vais étudier la question... euh par contre, pour en revenir à mon problème de départ, le coup des classes héritées pour avoir différent types de faces dans un même tableau, c une bonne idée ou pas ? (évidemment, je sais pas, du coup, si j'utiliserais la technique pour des faces, mais il se trouve que dans mon programme précédent, je faisais ça aussi pour les sons, les vaisseaux, les projectils, etc...) |
généralement non.
il vaux mieux avoir un tableau de triangles,
un tableau de quads...
qu'un tableau de trucs, où le truc tu connais son existance grâce à ton langage.... (je pense à faire des méthodes virtuelle display() par primitve).
rien ne t'empêche d'encapsuler via des virtuels/template tes polygones, mais fo fuir un test qu'il soit explicite ou implicite par triangle (au niveau du traçage).
généralement le hardware ne connais que le triangle (et les point sprites ), après fo voir.
donc soit tu fais une liste de triangles indépendants, soit une liste de triangle en strips ou en fan.
Marsh Posté le 26-03-2004 à 15:24:58
dans le cas chaque classe possède les mêmes fonctions (virtuelles, donc), c mieux ? enfin je sais bien que faire des tests du genre
if(tab[i]->type=="planet" ) ...
c pas une bonne idée. mais si je fais des trucs genre
tab[i]->display()
où tous les objets de tab sont dérivés d'une classe avec une fonction display virtuelle, c bon ? parce que par exemple, je pourrais comme ça avoir un seul tableau contenant tous les objets qu'il y a dans le jeu, et j'aurais juste à faire un ->loop() pour que chacun bouge, alors que sinon il me faudra un tableau de chasseurs, un tableau de fregates, un tableau de plantès, etc... sans compter que si un chasseur veut vérifier qu'il fonce pas dans une frégate, ou dans une planète, etc... bref, ce serais la merde, nan ? je sais pas si j'ai été très clair...
Marsh Posté le 26-03-2004 à 15:26:49
donc les display lists:
http://nehe.gamedev.net/data/lesso [...] ?lesson=12
le VBO:
http://nehe.gamedev.net/data/lesso [...] ?lesson=45
(ptet un peu compliqué)
Marsh Posté le 26-03-2004 à 15:31:04
euh là va falloir que je déconnecte, merci pour tout, je vais étudier tout ça tranquillement...
Marsh Posté le 26-03-2004 à 15:32:32
Yawen a écrit : dans le cas chaque classe possède les mêmes fonctions (virtuelles, donc), c mieux ? enfin je sais bien que faire des tests du genre |
non pas de problème à ce niveau.
tu fais ce que tu veux pour les objets de ton moteur.
c'est juste qu'il faut pas faire de trucs tordus au niveau primitive bas-niveau de l'API graphique.
spa compliqué: les ressources 3D sont consommées bien plus rapidement par le GPU que par le CPU, donc si tu fais des "opérations" CPU au niveau triangle, t'auras aucunes différences de perfs géométriques entre une tnt2 et une radeon 9800 pro.
donc par exemple les glbegin() / glvertex() par triangle, sans "encapsuler" ça dans une display list, c'est à proscrire.
Marsh Posté le 29-03-2004 à 16:46:41
si quelqu'un regarde encore un peu ce qui se passe par ici :
le VBO, ça a l'air bien, sauf que chez moi ça marche pas : le tutorial de nehe, quand je lance l'éxécutable, me dis qu'il ne trouve pas l'extension. en debuggant le programe, j'ai regardé la chaine renvoyée par glGetString, et effectivement, pas de VBO en vue... sauf que ma carte graphique c'est une radeon 9000 (mobility), donc ça m'étonnerais qu'elle ne gère pas ça... je suppose qu'il y a une mise à jour à faire quelque part, mais je sais pas trop où... (le compilateur date de 1998, il me semble... je suppose que les librairies sont loin d'être à jour...)
Marsh Posté le 29-03-2004 à 17:25:44
les catalysts, c pas les drivers de la carte graphique ?
Marsh Posté le 29-03-2004 à 17:54:47
parce que c'est une radeon mobility que j'ai (version pour pc portable), et c'est pas les même drivers que pour les radeon normales, sur le site d'ATI ils disent de prendre les drivers fournis par le constructeur du portable (enfin c'est ce que j'ai compris avec mes vagues notions d'anglais), et le problème c'est que le constructeur (dell) n'a pas l'air de vouloir mettre quoi que ce soit à jour...
Marsh Posté le 29-03-2004 à 18:08:25
ah ben en fait si, j'ai trouvé sur le site de dell, et effectivement, maintenant ça marche (mais j'avais déjà cherché sur le site de dell sans trouver...). bref, merci (en plus avec un peu de chance j'aurais moins de bugs...)
Marsh Posté le 30-03-2004 à 15:28:12
bon, alors maintenant, les VBO ça marche très bien dans mon programme, à part que je ne gagne absolument rien en performances... pourtant je suis sûr que c'est bien activé, puisque je détruit l'objet "normal" une fois chargé dans la mémoire de la carte graphique. Quand je lance le tutorial de NeHe (n°45, sur l'utilisation des VBOs, justement), sans les VBO je suis à 75fps, avec je suis à 85. Dans mon programme (qui affiche 20 000 faces), je tourne à 42fps, avec ou sans VBO. Est ce que j'ai fais une erreur quelque part, ou est ce que c'est juste que le gain de performance dépend de la config ? (parce que celui qui a fais le tutorial dis qu'il gagne pas mal de fps...)
Marsh Posté le 31-03-2004 à 14:50:37
ben quand je dis 42fps, c une moyenne, disons que ça oscille entre 36 et 50 fps. de plus, mon écran rafraichi en 60Hz (c'est un écran plat). Et enfin, selon le nombre de faces que j'affiche et la place qu'elles prennent sur l'écran (si elles sont loin, cachées, etc...), que j'affiche en plain écran ou en fenêtré, etc, ben ça change le nombre de fps. par contre, que j'active ou pas les VBO, ça change rien... mais je me demande si ça vient pas tout bêtement du fait que ce qui détermine la cadence de rafraichissement, c'est l'affichage lui même de la face, et non pas l'accès aux données. et les VBO, ça n'accélère que l'accès aux données... et puis sinon, en ce qui concerne la vsync, je sais absolument pas comment on configure ça... et je sais pas non plus à quoi ça sert (enfin je sais que la carte attend la synchronisation verticale de l'écran pour afficher une nouvelle image, mais ça change quoi ?)
Marsh Posté le 12-04-2004 à 00:08:35
Si tu n'es pas satisfait du framerate, une très bonne référence :
http://download.nvidia.com/develop [...] alysis.pdf
à savoir que le pb des performances est multidimensionel et ne repose pas sur un seul critère (vbo vs DrawTriangle).
LeGreg
Marsh Posté le 26-03-2004 à 13:19:03
Voilà, je suis en train de programmer un jeu en 3D, en utilisant openGL, et je me demande comment structurer les données :
j'ai pensé à utiliser une classe abstraite Face de laquelle je dérive d'autres classes, du genre FaceTriangle, FaceQuad, FaceMultiple (pour les faces ayant respectivement 3, 4 ou n sommets).
Comme ça, je pourrais utiliser un vector<Face*> pour définir un objet constitué de plusieurs faces, quel que soit le nombre de sommets de chaque face. Seulement je ne sais pas ce que donne cette méthode au niveau des performances (en particuliers pour l'allocation/libération de mémoire, c pas hyper simple...).
une autre solution serais d'avoir une classe Face avec une donnée membre indiquant le nombre de points, et chaque fonction (Draw, GetIntersection, etc...) testerais le nombre de points pour voir comment faire ce qu'elle a à faire. Mais c'est assez crade comme code, de mettre un
if(nbrPoints==3) {
glBegin(GL_TRIANGLES);
...
}
else if(nbrPoints==4) {
glBegin(GL_QUADS);
...
}
else {
glBegin(GL_TRIANGLE_FAN);
...
}
Pour chaque fonction, il faudrait refaire le test, c pas propre, sans compter l'impact sur les performances.
Enfin, je pourrais aussi n'utiliser que des faces triangulaires, mais c'est un peu con parceque par exemple pour trouver l'intersection d'une face avec une demi droite, une face ayant une forme compliquée, mais plane, demanderait plus de calculs si je la décompose en triangles que si je procède autrement
Et enfin, reste peut-être la solution miracle que je ne connais pas... donc si quelqu'un l'a (c un peu le but de ce message) ce serais cool de me la donner
J'ai déjà fais un programme qui tourne pas mal, en utilisant la méthode des classes dérivées, sauf qu'il est lent, le programme. Enfin je ne dis pas que ça vient de ça, mais bon...
En fait je compte recommencer le programme de zero, et donc c la première question que je me pose : comment structurer mes données...
---------------
~~ Yawen ~~