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

Auteur Sujet: Rapidité des transformations avec SFML  (Lu 3218 fois)

0 Membres et 1 Invité sur ce sujet

DexArio

  • Newbie
  • *
  • Messages: 16
    • Voir le profil
Rapidité des transformations avec SFML
« le: Mars 03, 2016, 10:35:38 pm »
Salut,

Je suis actuellement entrain de créer mes propres classes graphiques (= Sprites...) avec OpenGL. En comparant mes classes à celles d'SFML, j'ai remarqué que celles d'SFML étaient bien plus rapides (je parle ici des sprites). Après investigations, j'ai trouvé que calculer les transformations pour mes sprites prenait beaucoup de temps (j'utilise GLM). La différence est vraiment notable: j'ai fait une application test pour comparer et les résultats sont frappants: SFML -> 240 FPS, Moi -> 39 FPS. Quand J'enlève les transformations sur mes classes, je monte à 260 FPS. C'est donc le fait de calculer les transformations avec GLM qui cause énormément de lag. Je me demandais donc comment est-ce que SFML fait pour être aussi rapide. J'ai déjà épluché le code de sf::RenderTarger::draw(...) et de sf::Transformable::getTransform() mais mis à part le fait que SFML n'utilise pas GLM, je n'ai pas vu de différences notables (ex: SFML recalcule aussi les transformations à chaque fois qu'elles changent).

Je ne sais pas si c'est important mais voici comment est-ce que je calcule les transformations:

        if (m_updateNeeded)
        {
                glm::mat4 model, projection;

                /* Model matrix */
                /* Translating the sprite to its position and scaling it */
                model = glm::translate(model, glm::vec3(m_position.x, m_position.y, 0.0f));
                model = glm::scale(model, glm::vec3(m_scale.x, m_scale.y, 0.0f));

                /* Rotating the sprite (we translate it to its origin, rotate it and translate it back to where it was) */
                model = glm::translate(model, glm::vec3(m_rotationOrigin.x, m_rotationOrigin.y, 0.0f));
                model = glm::rotate(model, m_rotation, glm::vec3(0.0f, 0.0f, 1.0f));
                model = glm::translate(model, glm::vec3(-m_rotationOrigin.x, -m_rotationOrigin.y, 0.0f));

                /* Projection matrix */
                projection = glm::ortho(0.0f, (float)screenWidth, (float)screenHeight, 0.0f);

                m_mvp = projection * model;

                m_updateNeeded = false;
        }

        return m_mvp;

Sinon, pour le test que j'ai réalisé pour comparer marche de la manière suivante: j'ai un sprite de 32x32, que je draw() 768 fois (avec à chaque fois une position différente) pour couvrir une surface de 1024x768 px. Ainsi, les transformations doivent être recalculées 768 fois, ce qui crée beaucoup de lag avec mes classes.

(Aussi, je ne sais pas vraiment si ce topic est dans la bonne catégorie, de mon point de vue, je ne vois pas ça comme une demande d'aide mais plus comme une question, une inquisition).

Merci.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Rapidité des transformations avec SFML
« Réponse #1 le: Mars 03, 2016, 10:51:05 pm »
Tu as regardé le code source, mais pas au bon endroit apparemment :
https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/Transformable.cpp#L181-L203

Les transformations ne sont pas calculées et multipliées les une derrière les autres : puisque ce sont toujours les mêmes et combinées dans le même ordre (en ce qui concerne sf::Transformable), elles sont déjà pré-combinées et uniquement le calcul final optimisé est implémenté.

Fais la même chose avec sf::Transform, et tu devrais obtenir le même genre de performances qu'avec GLM.
Laurent Gomila - SFML developer

DexArio

  • Newbie
  • *
  • Messages: 16
    • Voir le profil
Re : Rapidité des transformations avec SFML
« Réponse #2 le: Mars 04, 2016, 06:51:10 pm »
J'ai joué un peu avec les transformations et j'ai fini par faire ça:

        float angle = -m_rotation * 3.141592654f / 180.f;
                float cosine = std::cos(angle);
                float sine = std::sin(angle);

                float x1 = m_scale.x * cosine;
                float y1 = m_scale.y * sine;
                float z1 = 0.f;
                float w1 = 0.f;
               
                float x2 = m_scale.x * -sine;
                float y2 = m_scale.y * cosine;
                float z2 = 0.f;
                float w2 = 0.f;

                float x3 = 0.f;
                float y3 = 0.f;
                float z3 = 1.f;
                float w3 = 0.f;

                float x4 = -m_rotationOrigin.x * x1 - m_rotationOrigin.y * -y1 + m_position.x + m_rotationOrigin.x * m_scale.x;
                float y4 = -m_rotationOrigin.x * -x2 - m_rotationOrigin.y * y2 + m_position.y + m_rotationOrigin.y * m_scale.y;
                float z4 = 0.0f;
                float w4 = 1.0f;


                m_mvp = glm::ortho(0.0f, (float)screenWidth, (float)screenHeight, 0.0f) *
                        glm::mat4(x1, y1, z1, w1, x2, y2, z2, w2, x3, y3, z3, w3, x4, y4, z4, w4);

Ce code est 2.4x plus rapide que l'ancien, c'est pas mal, mais c'est moins qu'SFML, qui est 6,4x plus rapide  :o
Cependant, il me reste d'autres optimisations à faire concernant d'autres fonctionnalités liées aux sprites.