[Résolu]Optimisation de la SFML

Optimisation de la SFML [Résolu] - C++ - Programmation

Marsh Posté le 07-07-2011 à 22:02:27    

Bonjour !
 
J'ai quelques soucis d'optimisation de la SFML qui me font baisser le framerate à 7-8 FPS, quand j'essaye d'afficher une map...
Il faut dire que je cherche un peu la bagarre en essayant d'afficher une map de 23*16 cubes soit 1150*800px 60 fois par secondes  :whistle:  
 
Avec la SDL ça passait très mal, du coup j'ai essayé avec la sfml, plus performante (a ce que j'ai lu sur d'autres forum), mais les résultats sont encore pires !
Du coup je me dis que j'ai sans doute mal utilisé cette libraire...
 
Voila comment j'ai procédé :
1: Déclaration de tous les Image et Sprite différents en global, juste avant le main
2: RenderWindow oApp(VideoMode(1200, 900, 32), "CROMGame", Style::Titlebar|Style::Close); toujours en global et au dessus du main
3: Début du main, oApp.SetFramerateLimit(60); oApp.UseVerticalSync(true);
4: Chargement de tous les Image et Sprite ainsi : oImage.LoadFromFile("chemindemonimage" ); sprSprite.SetImage(oImage);
5 : Boucle while avec dedans (dans cet ordre) :  
     gestion des événements
     oApp.Clear(); //Supprime tout ce qu'il y a sur l'écran
     Draw du screen (juste le contour)
     Draw du world (toutes les caisses, trous, sols présents sur la map, c'est ça qui ralentis tout)
     Draw du curseur personnalisé
     Draw du compteur de FPS
     oApp.Display(); //Affiche tous les draw
 
Au final, ça donne ça :
http://img198.imageshack.us/img198/1346/testapq.th.jpg
 
Le code complet est disponible à cette adresse :
http://lesgdo.org/perso/test.zip
 
Et en voici quelques parties importantes :

Code :
  1. //DECLARATION DES IMAGE ET SPRITE JUSTE AVANT LE MAIN
  2. //Images
  3. Image oCursor;
  4.     Sprite sprCursor;
  5. //Ecrans d'accueil, de jeu
  6. Image oGameScreen;
  7.     Sprite sprGameScreen;
  8. //Elements du monde
  9. Image oWorldNotSet;
  10.     Sprite sprWorldNotSet;
  11. Image oWorldFloorRock;
  12.     Sprite sprWorldFloorRock;
  13. Image oWorldCrateA;
  14.     Sprite sprWorldCrateA;
  15. Image oWorldGap;
  16.     Sprite sprWorldGap;
Code :
  1. //INITIALISATION DES IMAGE ET SPRITE
  2.     //Curseur ================
  3.     oCursor.LoadFromFile("data/img/cur.png" );
  4.         sprCursor.SetImage(oCursor);
  5.     //Ecran de jeu ===========
  6.     oGameScreen.LoadFromFile("data/img/gamescreen.bmp" );
  7.         sprGameScreen.SetImage(oGameScreen);
  8.     //World ==================
  9.     //Special
  10.     oWorldNotSet.LoadFromFile("data/img/world_notset.bmp" );
  11.         sprWorldNotSet.SetImage(oWorldNotSet);
  12.     //Floors
  13.     oWorldFloorRock.LoadFromFile("data/img/world_floor_rock.bmp" );
  14.         sprWorldFloorRock.SetImage(oWorldFloorRock);
  15.     //Crates
  16.     oWorldCrateA.LoadFromFile("data/img/world_crate_a.bmp" );
  17.         sprWorldCrateA.SetImage(oWorldCrateA);
  18.     //Gap
  19.     oWorldGap.LoadFromFile("data/img/world_gap.bmp" );
  20.         sprWorldGap.SetImage(oWorldGap);
Code :
  1. //FONCTION POUR DRAW LE WORLD
  2. void DrawWorld()
  3. {
  4.     int i, j;
  5.     Vector2<float>::Vector2<float> vPosWindow;
  6.     struct worldposblock vPosWorld;
  7.     for(i=0 ; i<WORLD_HEIGHT_CUBE ; i++)
  8.     {
  9.         for(j=0 ; j<WORLD_WIDTH_CUBE ; j++)
  10.         {
  11.             vPosWorld.hrz = j; vPosWorld.ver = i;
  12.             vPosWindow = CoordWorldBlocksToScreenPx(vPosWorld);
  13.             switch(nWorld[i][j])
  14.             {
  15.                 //=========================
  16.                 case WORLD_CUBE_FLOOR_ROCK:
  17.                     sprWorldFloorRock.SetPosition(vPosWindow);
  18.                     oApp.Draw(sprWorldFloorRock);
  19.                     break;
  20.                 //=========================
  21.                 case WORLD_CUBE_CRATE_A:
  22.                     sprWorldCrateA.SetPosition(vPosWindow);
  23.                     oApp.Draw(sprWorldCrateA);
  24.                     break;
  25.                 //=========================
  26.                 case WORLD_CUBE_GAP:
  27.                     sprWorldGap.SetPosition(vPosWindow);
  28.                     oApp.Draw(sprWorldGap);
  29.                     break;
  30.                 //=========================
  31.                 case WORLD_CUBE_NOTSET:
  32.                     sprWorldNotSet.SetPosition(vPosWindow);
  33.                     oApp.Draw(sprWorldNotSet);
  34.                     break;
  35.             }
  36.         }
  37.     }
  38. }


 
Pouvez vous m'expliquer pourquoi ça pêche, et comment régler ce problème plutôt frustrant?
Sans doute que la SFML n'est pas prévue pour cette utilisation, dans ce cas pouvez vous m'indiquer une librarie multiplateformes, qui gère le 2D de manière fluide?
 
Merci d'avance ;)


Message édité par crom29 le 08-07-2011 à 18:42:00

---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 07-07-2011 à 22:02:27   

Reply

Marsh Posté le 08-07-2011 à 12:43:35    

Y'a peut-être un problème avec ce qui pourrait être traçé hors-écran. Même si c'est cullé par le draw.
 

Code :
  1. void DrawWorld()
  2. {
  3.     int i, j;
  4.     Vector2<float>::Vector2<float> vPosWindow;
  5.     struct worldposblock vPosWorld;
  6.     int limit = 10;
  7.     for(i=0 ; i<WORLD_HEIGHT_CUBE ; i++)
  8.     {
  9.         for(j=0 ; j<WORLD_WIDTH_CUBE ; j++)
  10.         {
  11.             if( !limit-- ) return;
  12.            
  13.             vPosWorld.hrz = j; vPosWorld.ver = i;
  14.             vPosWindow = CoordWorldBlocksToScreenPx(vPosWorld);
  15.             switch(nWorld[i][j])
  16.             {
  17.                 //=========================
  18.                 case WORLD_CUBE_FLOOR_ROCK:
  19.                     sprWorldFloorRock.SetPosition(vPosWindow);
  20.                     oApp.Draw(sprWorldFloorRock);
  21.                     break;
  22.                 //=========================
  23.                 case WORLD_CUBE_CRATE_A:
  24.                     sprWorldCrateA.SetPosition(vPosWindow);
  25.                     oApp.Draw(sprWorldCrateA);
  26.                     break;
  27.                 //=========================
  28.                 case WORLD_CUBE_GAP:
  29.                     sprWorldGap.SetPosition(vPosWindow);
  30.                     oApp.Draw(sprWorldGap);
  31.                     break;
  32.                 //=========================
  33.                 case WORLD_CUBE_NOTSET:
  34.                     sprWorldNotSet.SetPosition(vPosWindow);
  35.                     oApp.Draw(sprWorldNotSet);
  36.                     break;
  37.             }
  38.         }
  39.     }
  40. }


 
Voir si les perfs décollent.
Au moins tu sauras que c'est le Draw qui limite.
 
Après il faudrait savoir comment le Draw est implémenté derrière: si c'est de l'OpenGl, et si t'est pas en OpenGl software.

Reply

Marsh Posté le 08-07-2011 à 15:39:03    

Merci de ta réponse
 
J'ai fait quelques tests en changeant la limite que tu m'a fait mettre :
 
Limit       Moyenne de FPS         Remplissage du world
----------------------------------------------------------
10                  60                            10blocs
23                  60                            1 ligne
24                  60                            1ligne+1bloc
30                  48                            1ligne+7blocs
35                  43                            1.5ligne
46                  35                            2 lignes
47                  32                            2 lignes+1bloc
 
Normalement aucun bloc n'est tracé en dehors de l'écran, toute la map est affichée (j'utiliserais certainement les caméras pour avoir un vrai monde, mais pour l'instant j'essaye de faire quelque chose de stable et fluide ^^).
 
Niveau OpenGL, je n'ai absolument aucune connaissance...
Qu'est ce que ça apporte en plus niveau 2D?
Est-ce qu'il faut le maitriser pour faire du 2D correct avec SFML?


Message édité par crom29 le 08-07-2011 à 15:41:23

---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 08-07-2011 à 15:52:26    

Si SFML utilise l'OpenGl tout est fait localement au GPU et ça devrait pas ramer pour 47 sprites donc quads. Même avec des glVertex().
 
Si quand ça rame l'utilisation CPU écrête (sur un core), a priori c'est que le traçage des sprites est fait en CPU vraiment pas super optimisé, ou que l'OpenGl est en software.

Reply

Marsh Posté le 08-07-2011 à 16:00:31    

Sinon il faut peut-être un sprite par cellule, et non réutiliser le même sprite en changeant sa position.

Reply

Marsh Posté le 08-07-2011 à 16:13:36    

Hmm, si j'ai bien compris, tu dessines un monde composé de tuiles 2D sur une grille fixe. Je n'ai pas trop regardé le détail de ton code, mais n'importe quelle machine de ces 15 dernières années est capable de te sortir du 60fps pour quelque chose d'aussi simple.
 
Là où ton code peut coincer au niveau FPS c'est si la fonction RenderWindow::Draw() implique un rafraîchissement de l'écran. En fait en regardant vite fait ton code, j'ai l'impression que toutes les fonctions de la classe RenderWindow impliquent un rafraîchissement implicite.
 
Cela dit je ne connais pas trop SFML, je connais surtout SDL. Avec SDL tu peux obtenir directement un pointeur sur le buffer video et faire une copie de tile/sprite via SDL_BlitSurface(). Une fois ton travail terminé, tu indique explicitement à SDL d'afficher ça à l'écran (via SDL_UpdateRect).
 
Il doit forcément y avoir un mécanisme similaire avec SFML. Même en faisant des calculs bien bourrin (image calculée à la volée à chaque trame + retaillage bicubique de 800x600 => 640x480), j'arrivais à obtenir du 30FPS en utilisant 10% d'un CPU d'un CoreDuo@2GHz.

Reply

Marsh Posté le 08-07-2011 à 17:42:07    

RenderWindow::Draw() ne rafraichit pas la fenêtre : si j'enlève le oApp.Clear(); et oApp.Display(); (présents dans le main pour rafraichir la fenêtre) j’obtiens une fenêtre vierge...


---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Marsh Posté le 08-07-2011 à 17:52:31    

grrr j'ai trouvé le problème...
SFML n'aime pas les virtualbox !
étrange je trouve parce que je peux jouer a des jeux 3D (comme OpenArena) sans problèmes avec, mais le 2D, ça coince...
Désolé de vous avoir embêté pour ça...


---------------
Mods: HAF922 | Shinobi XL White    GitHub     Admin de La Colère d'Aurile, serveur RP-Action Neverwinter Nights 2
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed