Pages: 1
Bonjour @tous,
Depuis quelques jours déjà je tente de rester au dessus de la barre des 100fps avec mon nouveau projet mais je crois que j'arrive à la limite de ce que peut donner ce moteur.
Mon but est de créer un jeu de shoot spatial dont les vaisseaux sont des sortes d'amas atomiques ; chaque "atome" correspondant à un objet spécifique (canon, réacteur, container etc etc). L’intérêt de la manip est de créer in-game un vaisseau totalement custom selon des règles particulières.
Coté code, il apparait évident et inévitable de créer une node par objet puisque chaque objet d'un type donné a un mesh différent (au pire il pourra être le même pour tous les vaisseaux, mais se déclinera en plusieurs versions). Mais quelle que soit la solution utilisée pour les mesh, celle concernant les nodes me semble inévitable : 1 node par objet (dites moi si je me trompe).
Sachant qu'un vaisseau peut comporter en moyenne une vingtaine d'objets (voire beaucoup plus si je trouve un moyen de gagner des fps), et je j'envisage des combats avec au moins une vingtaine de vaisseaux à l'écran, on arrive facilement à 400 nodes pour les vaisseaux (plus le décor).
Cela me fait arriver au problème suivant : les fps. En effet avec 400 nodes (contenant pour l'instant des spheres low poly), je tombe déjà à un framerate en dessous de 200 fps avec un core i7 (bon ok ya rien de multithreadé) qui si tout est affiché à l'écran peut descendre en dessous de 100 fps.
Ayant codé par dessus tout ça un moteur physique ultra léger qui arrive à prendre à lui tout seul moins de 1ms pour gérer 1000 vaisseaux de 20 spheres chacuns, je suis (comment dire...) frustré de voire que le rendu de 400 nodes prend 9ms...
J'ai déjà fait un système qui débranche les nodes non visibles à l'écran du graphe de scene afin d'arriver à ce minimum de 400 nodes à gérer pour le graph de scene... je ne vois plus quoi faire d'autre là.
Donc si quelqu'un ici à une suggestion à me faire, je suis preneur ^^.
Merci d'avance.
Aka
Hors ligne
Bonjour, tu as un core i7 c'est bien mais la carte graphique joue un rôle plus important dans le rendu. Le processeur exécute le programme et envoie les données à la carte graphique, qui elle, calcule tout le rendu! Donc avoir un processeur rapide c'est bien à condition d'avoir la carte graphique qui suit.
Maintenant, Irrlicht apprécie pas trop des scenes avec pleins de petit nodes. Il vaut mieux avoir quelques gros mesh. Par exemple, pour un mesh de 1 310 720 triangles je tourne à 245 fps. Par contre, avec 300 nodes pour un total d'environ 50 000 triangles je tournais à 185 fps.
Je pense qu'il faut plutot trouver une astuce pour n'avoir qu'un mesh par vaisseau. Le mieux serait de combiner les mesh dans un même buffer à l'aide d'un node perso que tu créerais.
Sinon tu as quoi comme carte graphique?
Hors ligne
J'ai une radeon HD 5800...
Effectivement après avoir lu à peu près tous les forums du net traitant de ces histoires de plusieurs nodes vs une seule node, j'en arrive à la conclusion qu'il me faudrait soit une methode me permettant de merger rapidement toutes mes nodes en une seule (maximum 100ms et dans ce cas je dis adieu aux rotations de me "sous nodes actuelles" (tant pis... les canons ne s'orienteront pas dans la direction voulue)), soit arriver à surcharger la methode drawAll du scene manager pour gérer intelligemment mes nodes en regroupant les nodes ayant un même mesh pour ne transférer ce mesh et sa texture qu'une seule fois ds la carte graphique.
Autres que ces 2 idées, je vois difficilement quoi faire d'autre avec les moyens du bord...
Hors ligne
où est le problème ? tu implemente un skellete sur ton vaiseaux et tu anim manuellement les bonnes pour faire tournée les cannons
le tout optimiser avec de l'hardware skinning, tu garde la possibiliter de pouvoire animer t'on vaiseaux, tu optimise le rendue, et c'est plus propre en terme d'utilisation
tout bénef
Hors ligne
Je ne crois pas avoir vu de fonctions permettant d'instancier un skeleton à la volée et lui rajouter des bones à la volée également... Je ne peux pas définir à l'avance la structure "moléculaire" que l'utilisateur final voudra avoir. C'est lui qui en fonction de certaines propriétés d'objets ajoutés au vaisseaux pourra ajouter une extension de skeleton au skeleton existant.
Si j'utilise un skeleton, il me faut avoir accès à des fonctions qui me permettent d'ajouter ou retirer des bones à la volée (ou merger 2 skeleton ensemble).
Celà est-il réalisable avec irrlicht ou bien suis encore dans un cul de sac ?
ps: lien vers mon topic sur le forum officiel irrlicht : http://irrlicht.sourceforge.net/forum/v … mp;t=46396
edit: après avoir regardé de plus près il s'avère que les bonescenenodes sont accessibles depuis un animatedmeshscenenode totalement fermé en écriture dans le sens ou le seul moyen d'obtenir tout ça est de charger un model animé depuis un fichier. Impossible de modifier à la volée le skeleton pour lui ajouter ou enlever des bones...
Faudrait-il que je crée une nouvelle node du genre DynamicAnimatedMeshSceneNode avec des fonctions permettant d'ajouter un bone à un autre ou retirer tous les bones fils d'un bone ? Comment mapper mes différents mesh statics sur ce skeleton, comment les skinner à la volée ? Ca ne me semble pas forcément évident et le gain de fps me semble peu probable (dans tous les cas il me faudra merger mes mesh en un seul un fois le tout skiné).
edit2: Je suis tombé la dessus et ça semble marcher plutôt bien : http://irrlicht.sourceforge.net/forum/v … instancing
Je vais essayer un peu cette voie la et si ça ne convient pas je chercherai à nouveau dans les autres directions.
Dernière modification par Akabane87 (30-05-2012 00:31:54)
Hors ligne
Il y a un truc qui me chiffonne. Au début, l'utilisateur a un vaisseau brut(sans modules), ensuite si l'utilisateur rajoute un module(un canon par exemple), il aura le choix entre divers emplacements prédéterminé ou il pourra le mettre n'importe où sur le vaisseau?
Je ne m'y connait pas trop mais si tu as des emplacements prédéterminés pour l'ajout de modules, tu créés un mesh vaisseau avec un skelette dont les fins de chaines s'arrêtent aux emplacements des modules. Ensuite tu créés tes modules avec des skelettes, puis tu combines les meshs et les skelettes ensemble dans irrlicht en créant une connection entre le skelette du vaisseau et ceux des modules.
Je n'ai peut-être pas été assez clair mais au final tu n'aurais pas de skelette à créer à la volée mais simplement une combination de mesh et créer une connection enfant/parent entre le 1er bone du module et le bone du vaisseau où doit être attaché le module.
Hors ligne
Héhé tu m'oblige à entrer dans le détail mais à la base tu pars de rien. Tu as un inventaire qui contient des pieces (moteurs, canon, container etc...) et parmi ces pieces tu as des générateurs. Ce sont ces générateurs qui vont "générer" un certain nombre de slots vides adjacents permettant d'y placer d'autres pieces (et donc d'autres générateurs qui permettront du coup d'étendre le nombre de slots vides). Du coup la géométrie du vaisseau est totalement inconnue à l'avance (mais doit être générée procéduralement pendant la phase de création du vaisseau).
Du coup si on en revient aux skeletons, je ne connais à l'avance que les skeletons engendrés par mes générateurs. Il me faudrait donc être capable de fusionner des skeletons ensemble (pas un simple attachement car des bones disparaissent totalement car redondants). Indépendamment de cet attachement un peu spécial, si je créais une relation enfant/parent entre mes mesh animés puis une relation d'attachement entre mes mesh statiques et les bones ou je vaux les placer, je pense que je retomberai plus ou moins dans le cas de départ : des mesh affichés uns à uns...
ps: j'ai implémenté un shader d'instancing et c'est over puissant je dois dire... 60 mesh pour le prix d'un c'est quand même pas négligeable ^^
Hors ligne
Quand je disais "parent/enfant" ce n'est pas ce que je voulais dire. En fait, tu prends un node custom, tu mets les vertex de tout tes meshs dans le même buffer et tu combine tes squelettes ensemble. Pour les combiner, tu ajoutes des relations enfant/parent sur tes bones uniquement. Du coup, tu n'as qu'un mesh avec 1 squelette. Le plus dur sera de gérer l'ajout et le retrait d'éléments puisqu'ils sont fusionnés. Là, par contre, c'est pas le bonheur.
Hors ligne
Ouai en théorie ça semble bien se goupiller mais en pratique je suis pas sûr de vraiment gagner en fps sur du shader instancing en intégrant un système de skeleton. En je ne parle pas de la complexité de la chose (sachant que je ne connais rien aux bones irrlicht pour l'instant).
Pour en revenir au shader instancing que je viens d'intégrer dans mon projet, je suis passé de 70 fps dans le pire des cas à 450 fps ds le même pire des cas. C'est largement plus que ce que j'avais pu espérer mais bon je n'ai pour l'instant qu'un seul type de mesh (une sphere) donc ça risque de baisser rapidement quand j'aurai un mesh par type d'objet dans X meshbuffer de shader instancing.
Hors ligne
Serait-il possible que tu fasses un tuto ou au moins un exemple avec une petite explication sur les shaders instancing? Parce que je t'avouerais que je ne connais pas. Sinon c'est vrai que ma solution est (très) compliquée à mettre en oeuvre mais ton concept de création de vaisseau l'est déjà au départ . D'ailleurs, j'ai du mal à m'imaginer comment tu comptes créer le modèle et ce que ça peut rendre. Mais pour ce genre de chose, les explications sont difficiles à donner.
En fait, je me l'imagine comme un vaisseau en voxels (gros voxels évidemment). Un peu comme dans minecraft, tu mets des éléments adjacents et la coque externe du vaisseau est créée en fonction des éléments présents. A la différence près que, en plus de la surface, tu as des éléments supplémentaires (canon, etc...). J'ai bien compris ton concept?
Hors ligne
Ok pour le tuto je verrai dès que j'ai le temps .
Pour mon projet oui c'est clair que c'est compliqué mais j'ai horreur de faire la même chose que tout le monde :p. Du coup j'imagine des concepts de jeu un peu space (c'est le cas de le dire ^^). En gros gros faut juste imaginer que t'auras des pieces de vaisseau aillant toutes une bounding sphere de taille identique collées les unes aux autres (du coup flottant les unes à côté des autres comme attirées et maintenues en cohésion par une sorte d'énergie). Faut pas imaginer des voxel avec un densité non visible à l'écran. Dans le trip du concept c'est le générateur qui génère/maintient la cohésion et alimente en énergie les éléments adjacents qui lui appartienne.
Par dessus tout ça il y a mon moteur physique fait pour l'occasion qui permet de gérer physiquement chaque vaisseau en fonction de sa géométrie et sa répartition du poids. Un réacteur provoque une poussée donnée selon les caractéristiques du moteur au point ou il est attaché. Si jamais il est mis n'importe comment il poussera le vaisseau pas droit en le faisant tourner etc...
En fait ce projet reprend un de mes anciens projet non terminé sur PSP (en 2D) et l'étend sur un shoot spatial 3D :p.
http://dreamraiser.forumactif.com/t20-square-force
Edit : Allez en cadeau une demo benchmark avec 10000 "vaisseaux" de 19 spheres avec un far de 500m : http://www.mediafire.com/download.php?ep97ud2b2q67558
Attention : vieux pc s'abstenir...
ZSQD pour avancer/strafer
AE pr roller
W pr enlever les frottements linéaires artificiels
X pour changer de vaisseau
C pour looter/reattacher la caméra
ESPACE pr réinitialiser la scene
Dernière modification par Akabane87 (31-05-2012 10:32:11)
Hors ligne
En effet, c'est original !^^ Par contre, tu pourrais afficher le nombres de triangles avec les fps. Parce que 57 fps sur une GTX590, ça me parait faible.
Un petit bout de code pour t'éviter d'éventuelles recherches...
/// variables
int lastFPS, lastNbTri;
lastFPS = lastNbTri = -1;
while(device->run())
{
/// rendu des environnements
driver->beginScene(true, true, SColor(252,200,200,200));
/// dessine la partie 3D
smgr->drawAll();
/// dessine la partie Interface
guienv->drawAll();
/// fin du rendu des environnements
driver->endScene();
/// affichage FPS et Nombre de Triangle
int fps = driver->getFPS();
int NbTri =driver->getPrimitiveCountDrawn();
if ((lastFPS != fps) || (lastNbTri != NbTri))
{
stringw str = L"Irrlicht Engine [";
str += driver->getName();
str += "] FPS: ";
str += fps;
str += " | TRIANGLES: ";
str += NbTri;
device->setWindowCaption(str.c_str());
lastFPS = fps;
lastNbTri = NbTri;
}
} // fin de la boucle
Hors ligne
Je fais ça ce soir en rentrant du taff et j'en profite pour corriger cet affreux affreux glitch qui fait tressauter l'affichage (j'ai du merder avec mon flush du dernier mesh buffer à chaque frame).
Je crois me rappeler avoir mis des sphères de 32 x 32 poly ds le geometry manager.
edit :
voila le nouveau lien : http://www.mediafire.com/?jrl149mnossulo5
j'ai remis le choix du driver/hlsl ou non/shader instancing ou non, mis pour les 2 versions (instancing ou non) le même nombre de poly sur mes spheres (1, 32, 32) et affiché le nombre de poly par frame. Chose incroyable en faisant ça, je suis passé de 16 16 à 32 32 poly pr mes sphères en version non instancing ce qui a apparemment activé l'utilisation de la directive hw_static d'hardware mapping d'irrlicht et fait qu'au final sur ma machine je suis maintenant plus rapide sans instancing qu'avec (dans les pires conditions sur cet exemple) avec dx9... comme quoi rien n'est acquis d'avance ^^
Dernière modification par Akabane87 (31-05-2012 20:20:36)
Hors ligne
Les VBO avec irrlicht s'active lorsque le mesh compte au moins 500 vertices (possibilité de changer la valeur de seuil).
Pour les test (affichage de 5,7 milions de triangles):
DX9 + Instancing : 86 fps
DX9 sans Instancing : 163fps
OPENGL4.2 + Instancing : 234fps mais pas de mesh affiché à l'écran!
OPENGL 4.2 sans Instancing : 162fps
Lorsque l'instancing n'est pas activé on a les faces ombrées correctement en fonction de la lumière mais lorsqu'il est activé on a un éclairage ambient seulement.
Edit : J'ai testé DX8 pour le fun. Franchement, t'embête pas avec lui car il est obsolète et j'ai obtenu 3 fps. Bon, le shader ne passe pas mais la différence parle d'elle-même.
Dernière modification par johnplayer (31-05-2012 20:56:21)
Hors ligne
mmhhh pas bien normal le coup des mesh non visibles en instancing opengl... glsl 4.2 également chez moi. Pour l'éclairage c'est normal le shader ne la gère pas pour le moment (et je compte pas tenter de l'améliorer vu les scores du coup...), et ma fct de draw ne les gère pas non plus.
Sinon globalement j'ai les même scores qui me paraissent assez honêtes. Je compte de toute façon pas afficher plus de 50 vaisseaux simultanément à l'écran et le nombre total d'instances non affichée est négligeable sur mon moteur physique. J'espère juste que ce sera suffisant pour gérer l'affichage des planètes (en LOD bien sûr) et des champs d'astéroids (au pire je ferai un mixte sprites/instancing de mesh avec recycling pour truander un max :p).
edit : en tous cas merci pour tes feedbacks
Dernière modification par Akabane87 (31-05-2012 21:01:24)
Hors ligne
De rien, dommage que les shaders n'est pas résolu ton problème. Par contre, les VBO m'avaient surpris moi aussi J'avais commencé une map very low poly 12 000 triangles avec 65 fps et lorsque je me suis aperçu de la limite des 500 vertices par mesh, j'ai augmenté le nombres de poly des meshs et après j'avais 185 fps pour 53 000 triangles.
Pour le seuil des VBO :
IrrlichtDriver* driver->setMinHardwareBufferVertexCount(nb_vertices_mini);
Hors ligne
Cool merci pour la ligne (j'étais presque parti pour modifier les sources d'irrlicht et tout recompiler xD).
Sinon nan c'est cool quand même. Le shader a bien résolu le problème mais les VBO ont été plus puissant donc je repasse sur mes nodes séparées avec leur propre mesh. C'est plus simple à gérer et j'ai pas besoin d'aller recoder du rendu pour gérer les lumières :p.
D'ailleurs au passage je conseille à tous ceux qui passent par ici de débrancher leur nodes qui ne sont pas rendues du graphe de scene plutôt que de compter sur le culling. Quand on a 200 000 nodes dans une scene comme c'est la cas sur mon benchmark, rien que le calcul du culling de chaque node suffit à trucider les fps. Un simple calcul de distance au carré par rapport à la camera comparé à la distance du far de la camera + un offset et un produit scalaire pour savoir si l'objet est dans le demi espace avant ou arrière et on vire toutes les nodes qui ne seront pas affichées (et on laisse le culling gérer le reste).
Hors ligne
Que veux-tu dire par "débrancher"?
Hors ligne
Un remove sur la node ou removeall pour virer ses fils si elle en a en ayant bien pris soin d'avoir un grab sur le pointeur ailleurs (histoire de pas devoir la reinstancier quand on voudra la "rebrancher").
Dans mon cas à moi j'ai une node correspondant au centre de masse de chacun de mes objets. Cette node a un fils qui est l'origine de mon vaisseau et qui a autant de nodes filles qu'il y a d'éléments (spheres) sur mon vaisseau. Quand je fais l'update de la physique, je parcours d'abord tous les objets pour mettre à jour leur position en fct de la physique et j'en profite pour calculer par la méthode indiquée plus haut s'il est visible ou non. S'il ne l'est pas je le débranche du graphe de scene en removant toutes ses nodes depuis la node du centre de masse. Dès qu'il redevient visible à nouveau, je le rebranche sur le graphe de scene.
Hors ligne
Pages: 1