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

  FORUM HardWare.fr
  Programmation
  C++

  [Résolu]Optimisation de la SFML

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Résolu]Optimisation de la SFML

n°2088047
crom29
Posté le 07-07-2011 à 22:02:27  profilanswer
 

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
mood
Publicité
Posté le 07-07-2011 à 22:02:27  profilanswer
 

n°2088184
bjone
Insert booze to continue
Posté le 08-07-2011 à 12:43:35  profilanswer
 

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.

n°2088245
crom29
Posté le 08-07-2011 à 15:39:03  profilanswer
 

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
n°2088250
bjone
Insert booze to continue
Posté le 08-07-2011 à 15:52:26  profilanswer
 

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.

n°2088254
bjone
Insert booze to continue
Posté le 08-07-2011 à 16:00:31  profilanswer
 

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

n°2088259
tpierron
Posté le 08-07-2011 à 16:13:36  profilanswer
 

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.

n°2088291
crom29
Posté le 08-07-2011 à 17:42:07  profilanswer
 

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
n°2088296
crom29
Posté le 08-07-2011 à 17:52:31  profilanswer
 

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

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

  [Résolu]Optimisation de la SFML

 

Sujets relatifs
SQL, select, count et optimisationAide à l'optimisation de requête
[PL/SQL] Optimisation d'un algoQuestion optimisation
[Batch] Optimisation de mon scripteOptimisation ecriture dans BDD à partir d'un table HTML [résolu]
optimisation de connexion php mysqlOptimisation interface et nombre de fichiers
Optimisation 2doptimisation du code c++
Plus de sujets relatifs à : [Résolu]Optimisation de la SFML


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