Aller au menu - Aller au contenu

[SFML] Ralenti d'affichage de pixels

Avec un filtre patchwork

Vous devez être inscrit pour pouvoir poster des messages

Page : 1 
Auteur Message
1 visiteur sur ce sujet (1 anonyme)
Page : 1 
Hors ligne Oubli4 # Posté le 26/12/2008 à 14:41:33
Magnum programmos sum
Avatar
Groupe : Membres
Bonjour à tous,
J'utilise SFML depuis peu et j'essaye de créer des filtres graphiques en l'occurrence un patchwork. Dans le chargement des pixels, l'affichage est trop long : 1.5 secondes en moyenne d'intervalle entre chaque boucle principale. Disons que j'essaye d'afficher 200 000 sf::Color très rapidement !
Voici le code, peut-être existe-t-il une méthode bien plus rapide, performante et surtout moins gourmande :
Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// "pixels" est de type : std::vector<std::vector<sf::Color> >

/// On prend les données de pixels de l'image
void Effect::LoadPixelsFromImage(const sf::Image& image)
{
    for (unsigned int i(0); i<pixels.size(); ++i)
    {
        for (unsigned int j(0); j<pixels[i].size(); ++j)
        {
            pixels[i][j]=image.GetPixel(i, j);
        }
    }
}
/// On affiche les données de pixels
void Effect::DrawMap(sf::RenderWindow& App, const unsigned int space)
{
    for (unsigned int i(0); i<App.GetWidth(); i+=space)
    {
        for (unsigned int j(0); j<App.GetHeight(); j+=space)
        {
            App.Draw(sf::Shape::Rectangle(i, j, i+space, j+space, pixels[i][j]));
            // "space" correspondant à la largeur du cube de pixel dégradé dans le patchwork
        }
    }
}

Merci d'avance.

Les As de la Fortune, le jeu de hasard d'Oubli4
 
Hors ligne Hertzien' # Posté le 26/12/2008 à 15:14:56
C++, C(encore)++ fort !
Avatar
Groupe : Membres
Peut être utiliser les post-effects ?

Mon problème : [FFMpeg] Installation
Notre équipe : C++ (au complet !)
SuperTux : Le jeu qui innove !
SFML - Anim : Ma classe C++ pour gérer les sprites SFML animés
 
Hors ligne Oubli4 # Posté le 26/12/2008 à 16:23:00
Magnum programmos sum
Avatar
Groupe : Membres
Justement à quoi sert cette classe ?
Elle permet d'intégrer ses filtres au programme ?

Les As de la Fortune, le jeu de hasard d'Oubli4
 
Hors ligne Laurent Gomila # Posté le 26/12/2008 à 17:11:49
Groupe : Membres
Les post-fx permettent d'appliquer des petits traitements à chaque pixel de l'image affichée. Mais cela utilise les shaders et n'est donc pas compatible avec les vieilles configurations.

Ceci-dit ta façon de faire peut être très largement optimisée. Optimise aussi ton stockage : une seule dimension contigüe en mémoire sera bien plus rapide d'accès.

Par exemple, copie les pixels d'un coup et non un par un
Code : C++
1
2
3
4
5
void Effect::LoadPixelsFromImage(const sf::Image& image)
{
    // pixels est un vector<sf::Uint8>
    memcpy(&pixels[0], image.GetPixelsPtr(), image.GetWidth() * image.GetHeight() * 4);
}


EDIT (désolé j'ai eu des invités entre temps ;) )

Ensuite pour l'affichage, au lieu d'afficher des rectangles, travaille sur ton tableau de pixels en mémoire et lorsque tu as fini d'appliquer ton effet, tu remplis à nouveau une image (Image::LoadFromPixels) avec et tu l'affiches via un sprite de la taille de l'écran.

Si tu fais tout cela ce sera suffisamment rapide pour avoir plusieurs dizaines d'images par seconde ;)
Édité le 26/12/2008 à 23:32:32 par Laurent Gomila
Hors ligne magnanime # Posté le 26/12/2008 à 23:28:38
Avatar
Groupe : Membres
Attention, il ne faut pas oublier de caster.
Hors ligne Laurent Gomila # Posté le 26/12/2008 à 23:31:09
Groupe : Membres
Caster quoi ?
Hors ligne magnanime # Posté le 26/12/2008 à 23:52:59
Avatar
Groupe : Membres
Les deux premiers arguments de 'memcpy' sont de type 'void*' alors que les paramètre envoyé sont de type 'Uint8*' je présume. J'ai donc pensé qu'un 'reinterpret_cast' serait approprié.
Apparemment il n'est pas necessaire, je m'excuse du dérangement.
Hors ligne Chlab_lak # Posté le 27/12/2008 à 00:05:08
Tendou : Royaume de dieu
Avatar
Groupe : Membres
@Laurent Gomila: Ce n'est peut-être pas le bonne endroit, et c'est peut-être déjà prévu, ou déjà fait, mais pourquoi ne pas implémenter des itérateurs de pixel dans la classe sf::Image (du style sf::Image::PixelIterator) ? Et ensuite utiliser les algorithmes de la SL:
Code : C++
1
std::for_each(myImage.Begin(), myImage.End(), sf::Image::PixelEffect::ToGrayVariation());

Après, bien sûr, tout dépend de la manière donc tu gères tes pixels en interne pour rendre ça utilisable (je parle notamment de vitesse d'execution). Si, par exemple, tu gères tes pixels par un tableau contigu (ortho?) en mémoire de uint23_t, PixelIterator ne serait qu'un typedef de uint32_t*, ce qui serait l'itérateur parfait niveau vitesse (enfin, il ne me semble pas qu'il y ait d'itérateur plus rapide qu'un pointeur).
Édité le 27/12/2008 à 02:22:40 par Chlab_lak
 
Hors ligne Laurent Gomila # Posté le 27/12/2008 à 11:15:41
Groupe : Membres
Citation : Pas de titre
Les deux premiers arguments de 'memcpy' sont de type 'void*' alors que les paramètre envoyé sont de type 'Uint8*' je présume. J'ai donc pensé qu'un 'reinterpret_cast' serait approprié.

Effectivement, mais la conversion de X* vers void* est toujours implicite (par contre le contraire ne l'est pas en C++) ;)

Citation : Pas de titre
Ce n'est peut-être pas le bonne endroit, et c'est peut-être déjà prévu, ou déjà fait, mais pourquoi ne pas implémenter des itérateurs de pixel dans la classe sf::Image (du style sf::Image::PixelIterator) ?

Dans ce cas, étant donné que sf::Image représente un tableau 2D, il me faudrait 3 types d'itérateurs :
- Itérateur sur lignes
- Itérateur sur colonnes
- Itérateur sur pixels
La classe deviendrait vite pleine de fonctions qui ne servent qu'à itérer (8 par itérateur = 24 fonctions !!).
Mais surtout, je ne pense pas que fournir une telle interface soit pertinent. Le rôle premier de sf::Image n'est pas la manipulation avancée des pixels pour appliquer des filtres ou autres. Ca c'est un besoin qui dépasse le cadre de SFML et qui nécessiterait plutôt une classe par dessus sf::Image.
Édité le 27/12/2008 à 11:16:57 par Laurent Gomila
Hors ligne Chlab_lak # Posté le 27/12/2008 à 14:46:05
Tendou : Royaume de dieu
Avatar
Groupe : Membres
Hors ligne Fvirtman # Posté le 27/12/2008 à 17:00:08
Avatar
Groupe : Membres
Je ne connais pas trop SFML, donc je dis peut etre une connerie :
Mais j'ai l'impression que tu BLIT x*y fois 1 pixel.

Dans toutes les API graphiques que je connais, blitter pixel par pixel = effondrement des performances.

L'idée générale est de réussir a récupérer tous les pixels dans un tableau en RAM, de modifier tout ce que tu veux dans ce tableau de façon "normale", puis de tout reblitter d'un coup sur l'image finale.

--- "Toute tâche répétitive est automatisable..." ---
Tuto C/C++ basés sur des exemples :
http://perso.numericable.fr/~fvirtman/info/tuto/index.html
Mes programmes a peu pres finis :
http://perso.numericable.fr/~fvirtman/progs/index.html
 

Retour au forum "Langage C++" ou à la liste des forums

Vous devez être inscrit pour pouvoir poster des messages