Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Dessin d'un grand nombre de carrés mobiles  (Lu 2918 fois)

0 Membres et 1 Invité sur ce sujet

Totocap

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Dessin d'un grand nombre de carrés mobiles
« le: Juillet 04, 2013, 06:58:33 pm »
Salut !

Débutant dans le C++ et dans la SFML (que j'adore  ;D ), j'ai essayé de faire un petit test pour voir si je pouvais m'en sortir : créer des entités représentées sous forme de carrés et bougeant d'un mouvement aléatoire tout en restant à 60 FPS. Mais j'aimerais en dessiner plusieurs milliers voire millions à l'écran, donc faire un code pas mal optimisé.
Je rappelle que ceci n'a pas d'autre but que de tester la SFML, alors ne cherchez pas de sens caché et profond !


D'abord, j'avais essayé avec un vector de RectangleShapes que je dessinais une par une. Bien sûr, ce n'était pas terrible et au bout d'environ 1000 carrés dessinés à l'écran à chaque tour de boucle, je tombais à 50 FPS. Sachant que tous les 1/60ème de seconde (pour les 60 FPS), je devais donner une nouvelle position à chaque carré puis le dessiner, cela représentait pas mal d'appels à draw.


La seconde idée que j'ai eu et celle pour laquelle je poste ici, est d'utiliser un Vertex Array et donc de ne faire qu'un seul appel à draw. Et après les tests, cela marche nickel, les carrés sont dessinés très rapidement !
Là d'où vient le problème c'est que je n'arrive qu'à en dessiner que 16 000 environ avant d'être à 50 FPS.

J'ai regardé quelle était la fonction qui me ralentissait tout et c'est celle-ci :
// Créé un tableau de Vertex
void Fourmiliere::creerVerArr() {
   
    // On vide le Vertex Array
    verArr.clear();
   
    // Pour toutes les fourmis de la fourmilière ...
    for (int i = 0; i < fourmiliere.size(); ++i) {
       
        // ... on les fait bouger ...
        fourmiliere[i]->Move();
       
        // ... et l'on ajoute les vertex les composant au Vertex Array
        verArr.append(fourmiliere[i]->getVertex()[0]);
        verArr.append(fourmiliere[i]->getVertex()[1]);
        verArr.append(fourmiliere[i]->getVertex()[2]);
        verArr.append(fourmiliere[i]->getVertex()[3]);
    }
}
En fait, cette fonction est appelée à chaque tour de boucle. Elle vide le Vertex Array pour le remplir avec les nouveaux Vertex (4 par carré, "Fourmi"), qui ont changé de position par rapport au tour de boucle précédent puisque les carrés bougent d'un mouvement aléatoire.

Donc je pense que le fait de demander à chaque tour de boucle à bouger chaque Vertex puis à recréer un Vertex Array est vraiment lent ...

Auriez vous une solution ?

Si mon explication n'est pas claire, n'hésitez pas à me poser des questions. Je vous mets mon code entier (assez court et commenté au maximum) : https://www.dropbox.com/s/5zj30bo1w1cyt30/Fourmis1.zip
Vous pouvez appuyer sur la touche directionnelle droite pour créer plusieurs centaines voire milliers de "Fourmis" d'un coup, pour tester.

Merci d'avance,
Totocap.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #1 le: Juillet 04, 2013, 07:46:13 pm »
Citer
Donc je pense que le fait de demander à chaque tour de boucle à bouger chaque Vertex puis à recréer un Vertex Array est vraiment lent ...
Pas forcément non. Ce n'est pas si coûteux que ça.

Fais le test suivant : ne fait aucun calcul, aucune mise à jour, dessine juste ton vertex array et vois combien tu as de FPS. Ensuite la même chose, toujours sans update, mais en vidant/remplissant quand même à chaque fois le vertex array.
Laurent Gomila - SFML developer

Totocap

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #2 le: Juillet 04, 2013, 08:11:19 pm »
Donc au lancement, dans les trois situations (normale, test 1 et test 2), je ne suis déjà qu'à 58 FPS au lieu de 60 ...

Après, j'ai créé des "Fourmis" jusqu'à tomber à 50 FPS (bon, ce n'est pas précis, mais ça montre quand même l'écart) :
- situation normale : 16 000 "Fourmis"
- test 1 : 100 000 "Fourmis"
- test 2 : 40 000 "Fourmis"

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #3 le: Juillet 04, 2013, 08:36:19 pm »
Ok, donc ton update prend un temps non négligeable (2.5x moins de fourmis) et le remplissage du vertex array aussi (environ le même facteur).

Au niveau du vertex array je ne pense pas qu'il y ait grand chose à optimiser. Ce que tu peux faire, c'est que chaque fourmi modifie directement ses vertex dans le vertex array, plutôt que 4 vertex à part que tu dois ensuite recopier dans le vertex array. Comme ça tu économises le clear() et les append(). T'as juste à faire des Move().
Laurent Gomila - SFML developer

Totocap

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #4 le: Juillet 04, 2013, 09:31:38 pm »
Merci, ça a déjà amélioré un peu (5000 Fourmis de plus, donc 21 000 environ).

Mais il doit y avoir un sérieux problème d'optimisation dans mon code car dès le départ je commence à 57-58 FPS avec une seule Fourmi affichée ... Cela ne vient peut être pas de ma compréhension de la SFML mais de ma compréhension du C++ (peut être une erreur bête), comme je suis débutant ...


Edit : En enlevant ma limitation des FPS dans le main grâce à la Clock (pour ne dessiner que toutes les 1/60ème de seconde) et en passant par une FrameLimit à 60 sur ma RenderWindow, j'arrive à 100 000 Fourmis pour 50 FPS ... Je ne comprends pas trop pourquoi.

Edit 2 : En fait le FPS n'est carrément pas stable, du coup, c'est pas pratique.
« Modifié: Juillet 04, 2013, 10:10:27 pm par Totocap »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #5 le: Juillet 04, 2013, 10:19:15 pm »
Tu ne devrais pas faire ça. Déjà, la fréquence de dessin ne doit pas être couplée à la fréquence d'update. Idéalement, le graphisme doit être synchronisé sur la synchro verticale pour un rendu optimal, et les updates doivent utiliser un algorithme de timestep fixe avec accumulateur (il y a plein d'articles à ce sujet, mais le plus populaire est celui-ci), si tu as vraiment besoin d'un timing très précis.
Laurent Gomila - SFML developer

Totocap

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #6 le: Juillet 04, 2013, 10:27:35 pm »
Merci pour l'article, il a l'air super  :)

Mais même si dans ma boucle limitée à 60 tours par seconde je traite les update et le dessin (ce que je vais changer grâce à l'article), je devrais pouvoir gérer plus de Fourmis que ça, non ? Et pourquoi dès le début je n'arrive pas à atteindre les 60 FPS mais reste scotché à 58 ?  ???

Dans le tutoriel sur les Vertex, tu disais que "les cartes graphiques modernes sont plutôt conçues pour traiter les triangles par lots de plusieurs milliers, voire millions.".

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #7 le: Juillet 05, 2013, 08:03:37 am »
Je n'ai pas de réponse précise à ces questions, ça dépend tellement de ton système (hardware et software) et du reste de ton programme.

La programmation graphique n'est malheureusement pas une science exacte.

Sinon, question bête, tes pilotes graphiques sont bien à jour ?
Laurent Gomila - SFML developer

Totocap

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Dessin d'un grand nombre de carrés mobiles
« Réponse #8 le: Juillet 05, 2013, 11:31:40 am »
Oui, je pense que oui :)

Et bien merci pour ton aide, Laurent, je vais essayer d'optimiser le code avec les dernières astuces que tu m'as filé.
« Modifié: Juillet 05, 2013, 01:29:00 pm par Totocap »

 

anything