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

Auteur Sujet: [SFML 2.0] 9-slice scaling - souci de RenderTexture  (Lu 9295 fois)

0 Membres et 1 Invité sur ce sujet

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] 9-slice scaling - [Résolu / code source dispo]
« Réponse #15 le: Mai 09, 2013, 02:33:04 pm »
Citer
le getTextureResize est là car en effet je me demandais à quel point c'était coûteux ou non de refaire le redimensionnement des 9 sprites et les blitter à chaque frame
Le redimensionnement : c'est quasiment gratos.
Le dessin : si tu n'as que quelques NinePatch ça ne va pas changer la face du monde ; maintenant, si tu commences à en avoir quelques centaines ou milliers, là ça vaut le coup de réduire le nombre d'appels internes à draw.

Note que le terme "blitter" est préhistorique (et, accessoirement, n'existe pas en français), il fait référence à une technique complètement désuète : "coller" les pixels un à un pour dessiner quelque chose. Tu devrais prendre l'habitude de ne plus l'utiliser, sinon tu vas passer pour un vieux sur les forums ;D
« Modifié: Mai 09, 2013, 02:35:43 pm par Laurent »
Laurent Gomila - SFML developer

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Re : [SFML 2.0] 9-slice scaling - [Résolu / code source dispo]
« Réponse #16 le: Mai 09, 2013, 02:45:28 pm »
Note que le terme "blitter" est préhistorique (et, accessoirement, n'existe pas en français), il fait référence à une technique complètement désuète : "coller" les pixels un à un pour dessiner quelque chose. Tu devrais prendre l'habitude de ne plus l'utiliser, sinon tu vas passer pour un vieux sur les forums ;D

Autant pour moi ^^, je vais éviter d'en parler alors ^^ !

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Je reviens sur un petit problème que je ne comprends pas bien !
J'ai remarqué après avoir passé mon programme à quelques amis pour tester que certains voyaient le programme planté à un moment précis.
Ayant recherché la ligne de code où ça plantait c'était incompréhensible, car c'était un glDrawElement qui faisait crasher l'appli (celui de ma skybox), et qui n'avait strictement rien à voir au niveau de la manip pour faire crasher. En gros c'est comme si quelquechose avait massacré ma VRAM d'un coup.

Après quelques recherches j'ai remarqué que le souci venait finalement de ma nouvelle classe NinePatch, et plus particulièrement de sa fonction getTextureResize() qui est sensé écrire les données dans un RenderTexture et me renvoyer la texture correspondante à la fin des draw.


NinePatch.cpp
sf::Texture NinePatch::getTextureResize(sf::Vector2f size)
{
        float wScale = (size.x - m_rect[0].width - m_rect[2].width) / m_rect[1].width;
        float hScale = (size.y - m_rect[0].height - m_rect[6].height) / m_rect[3].height;

        sf::Sprite subImages[9];
        for(int i=0;i<9;i++)
        {
                subImages[i]=m_subImages[i];
        }

        sf::RenderTexture renderTexture;
        renderTexture.create(size.x,size.y);
        renderTexture.clear(sf::Color::Transparent);

        subImages[0].setPosition(0,0);
        renderTexture.draw(subImages[0]);

        subImages[1].setPosition(0+m_rect[0].width, 0);
        subImages[1].setScale(wScale,1);
        renderTexture.draw(subImages[1]);

        subImages[2].setPosition(0+m_rect[0].width+m_rect[1].width*wScale, 0);
        renderTexture.draw(subImages[2]);

        subImages[3].setPosition(0, 0+m_rect[0].height);
        subImages[3].setScale(1,hScale);
        renderTexture.draw(subImages[3]);

        subImages[4].setPosition(0+m_rect[3].width, 0+m_rect[1].height);
        subImages[4].setScale(wScale,hScale);
        renderTexture.draw(subImages[4]);

        subImages[5].setPosition(0+m_rect[3].width+m_rect[4].width*wScale, 0+m_rect[2].height);
        subImages[5].setScale(1,hScale);
        renderTexture.draw(subImages[5]);

        subImages[6].setPosition(0, 0+m_rect[0].height+m_rect[3].height*hScale);
        renderTexture.draw(subImages[6]);

        subImages[7].setPosition(0+m_rect[6].width, 0+m_rect[1].height+m_rect[4].height*hScale);
        subImages[7].setScale(wScale,1);
        renderTexture.draw(subImages[7]);

        subImages[8].setPosition(0+m_rect[6].width+m_rect[7].width*wScale, 0+m_rect[2].height+m_rect[5].height*hScale);
        renderTexture.draw(subImages[8]);

        renderTexture.display();

        return renderTexture.getTexture();
}

 



Le programme ne plante pas si je commente "renderTexture.create(size.x,size.y);".
Bien sûr en résultat dans ce cas je n'ai rien comme texture finale, mais c'est pour l'instant la meilleure piste que j'ai pour régler ce souci !

Pour information, le code a été testé sur plusieurs PCs, et aux retours de configs de chacun d'entre-eux, la seule information commune aux PCs qui crachent est qu'ils sont équipés de cartes nVidia !

Voilà, je n'arrive pas à comprendre plus et j'aurais besoin d'aide désormais pour résoudre ce petit souci !

Merci d'avance !
« Modifié: Mai 11, 2013, 11:35:51 am par Dragonic »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #18 le: Mai 11, 2013, 12:05:20 pm »
Ce qui serait génial pour t'aider, c'est un code complet et minimal qui reproduit le problème. Pas tout ton bazarre d'origine, vraiment un code réécrit depuis zéro, qui ne fasse que reproduire le problème et rien d'autre.
Laurent Gomila - SFML developer

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #19 le: Mai 11, 2013, 12:13:07 pm »
Je peux essayer, en espérant que le code minimal suffira en effet !

Mais sinon pour reproduire le problème, il semblerait qu'il suffit simplement d'utiliser la classe NinePatch que j'ai présenté page précédente, de récupérer une texture avec la fonction getTextureResize(), et ensuite plus loin de draw un objet OpenGL (pas confirmé qu'il faille forcément un VAO ou autre). Je reprécise qu'il semblerait que le bug n'apparaisse qu'avec des PCs équipés nVidia.

Je vais essayer de faire un code minimal, ce qui n'est pas forcément si simple vu que le projet actuel compte quelques 50000 lignes de codes ^^ ! Je vais essayer donc de faire un mini-projet à part pour aboutir au résultat.

Eroy

  • Jr. Member
  • **
  • Messages: 60
    • Voir le profil
    • E-mail
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #20 le: Mai 11, 2013, 12:18:31 pm »
Citer
0+m_rect[0].width
? :o

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #21 le: Mai 11, 2013, 12:22:49 pm »
Citer
0+m_rect[0].width
? :o

Cette fonction est en partie un copié-coller d'une autre (draw() : voir page précédente) dans laquelle il y avait un paramètre à la place du "0"! j'ai laissé tel quel pour ne pas oublier vu que j'ai pas commenté mon code encore !

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #22 le: Mai 11, 2013, 01:00:46 pm »
J'ai réussi à créer un code minimal reproduisant le problème :

#include <GL/glew.h>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>

using namespace std;
using namespace sf;

void createSquare(GLuint &vaoID, GLuint &vboID, GLuint &iboID) {
        float* vertices = new float[12];  // Sommets du carré

        vertices[0] = -0.5; vertices[1] = -0.5; vertices[2] = 0.0; // Coin en bas à gauche
        vertices[3] = -0.5; vertices[4] = 0.5; vertices[5] = 0.0; // Coin en haut à gauche
        vertices[6] = 0.5; vertices[7] = 0.5; vertices[8] = 0.0; // Coin en haut à droite
        vertices[9] = 0.5; vertices[10] = -0.5; vertices[11] = 0.0; // Coin en bas à droite

        GLubyte Indices[] = {
    // Top
    1, 2, 0,
    3, 0, 2
        };

        glGenVertexArrays(1, &vaoID); // Créer le VAO
        glBindVertexArray(vaoID); // Lier le VAO pour l'utiliser

        glGenBuffers(1, &vboID); // Générer le VBO
        glBindBuffer(GL_ARRAY_BUFFER, vboID); // Lier le VBO
        glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); // Définir la taille, les données et le type du VBO

        glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Définir le pointeur d'attributs des sommets

        glGenBuffers(1, &iboID);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

        glEnableVertexAttribArray(0); // Désactiver le VAO
        glBindVertexArray(0); // Désactiver le VBO

        delete [] vertices; // Supprimer les sommets
}

Texture getTextureFromRenderTexture()
{
    RenderTexture renderTexture;

    if(!(renderTexture.create(50,50)))
                std::cout<<"failed create renderTexture"<<std::endl;

    return renderTexture.getTexture();
}

int main()
{
        RenderWindow window;
        window.create(VideoMode(800, 600), "test bug RenderTexture", Style::Default, ContextSettings(32));
    window.setVerticalSyncEnabled(true);

    GLenum initialisationGLEW( glewInit() );

    if(initialisationGLEW != GLEW_OK)
    {
        cout << "Erreur d'initialisation de GLEW : " << glewGetErrorString(initialisationGLEW) << endl;
    }

    Event event;
    bool running=true;

    unsigned int vaoID; // VAO
    unsigned int vboID; // VBO
    unsigned int iboID; // IBO
    createSquare(vaoID, vboID, iboID);

    Texture texture;

    while (running)
    {
        window.setActive();

        while (window.pollEvent(event))
        {
                if (event.type == Event::Closed)
            {
                // on stoppe le programme
                running = false;
            }
                else if ((event.type == Event::KeyPressed) && (event.key.code == Keyboard::T) )
                        {
                         texture = getTextureFromRenderTexture();
                        }
        }

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glBindVertexArray(vaoID); // Lier le VAO

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);

        glBindVertexArray(0); // Délier le VAO

        window.display();
    }

    window.close();

    return 0;
}
 

Le programme plante sur mon PC nVidia si j'appuie sur T, au niveau du glDrawElements !
J'ai essayé avec ceci à la place de l'utilisation du VAO :
glBegin(GL_LINES);
  glVertex2i(0,0);glVertex2i(0,1);
  glVertex2i(0,0);glVertex2i(1,0);
  glVertex2i(0,0);glVertex3i(0,0,1);
glEnd();

Et cela ne plante pas lors de l'appuie sur T.

De même, testé à l'instant avec seulement "glDrawArrays(GL_TRIANGLES, 0, 3);" (donc sans me servir de l'IBO), et aucun problème. Il semblerait donc que le bug se limite à l'utilisation de glDrawElements.

Et enfin, autre détail, si  "texture = getTextureFromRenderTexture();" est placé avant la boucle principale il n'y a aucun problème. Mais dès qu'il est dedans (par forcément au sein donc d'une réponse à un Event), le programme plante.

A noter donc que si je commente le "renderTexture.create(50,50)" il n'y a aucun problème ! La cause du problème semble donc venir de là !

Voilà, je peux difficilement faire plus précis ^^ !
« Modifié: Mai 11, 2013, 01:09:07 pm par Dragonic »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #23 le: Mai 11, 2013, 01:11:42 pm »
1. Lis le tutoriel correspondant (Fenêtre et OpenGL), il te manque les push/popGLStates.

2. Appelle window.setActive après l'appel à getTextureFromRenderTexture : là tu ne sais pas quel contexte est actif, puisque celui qui l'était (la RenderTexture) vient d'être détruit.
Laurent Gomila - SFML developer

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #24 le: Mai 11, 2013, 01:16:04 pm »
1. Lis le tutoriel correspondant (Fenêtre et OpenGL), il te manque les push/popGLStates.

2. Appelle window.setActive après l'appel à getTextureFromRenderTexture : là tu ne sais pas quel contexte est actif, puisque celui qui l'était (la RenderTexture) vient d'être détruit.

De mettre le "window.setActive()" après la boucle d'evenement (et donc après l'appel à getTextureFromRenderTexture) corrige en effet le souci !

Pour  push/popGLStates je les ai bien sûr vu dans le tuto, mais je les ai pas mis vu que dans cet exemple je ne draw aucun élément SFML. Sont-ils tout de même obligatoire !

EDIT : en effet j'aurais du faire attention que les  push/popGLStates n'était pas là que pour les draw, car si j'entoure le getTextureFromRenderTexture de ces deux instructions le programme ne plante plus. Faut-il en retenir que strictement tous les éléments du module graphique SFML ne doivent être manipulés qu'à travers push/popGLStates à partir du moment où la RenderWindow est active ?

Et la dernière question, c'est pourquoi ce genre de problème n'est pas retourné sur des PCs équipés de cartes ATI (du moins c'est ce que je constate avec les quelques tests fait par des amis) ?
« Modifié: Mai 11, 2013, 01:59:18 pm par Dragonic »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #25 le: Mai 11, 2013, 03:32:10 pm »
Citer
en effet j'aurais du faire attention que les  push/popGLStates n'était pas là que pour les draw, car si j'entoure le getTextureFromRenderTexture de ces deux instructions le programme ne plante plus. Faut-il en retenir que strictement tous les éléments du module graphique SFML ne doivent être manipulés qu'à travers push/popGLStates à partir du moment où la RenderWindow est active ?
Ben, dans ta fonction, tu fais bien des draw non ? :P

Citer
Et la dernière question, c'est pourquoi ce genre de problème n'est pas retourné sur des PCs équipés de cartes ATI (du moins c'est ce que je constate avec les quelques tests fait par des amis) ?
Faut pas chercher d'explication à ce genre de truc. Qui sait ce que font les drivers graphiques...
Laurent Gomila - SFML developer

Dragonic

  • Newbie
  • *
  • Messages: 46
    • Voir le profil
Re : Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #26 le: Mai 11, 2013, 03:52:00 pm »
Citer
en effet j'aurais du faire attention que les  push/popGLStates n'était pas là que pour les draw, car si j'entoure le getTextureFromRenderTexture de ces deux instructions le programme ne plante plus. Faut-il en retenir que strictement tous les éléments du module graphique SFML ne doivent être manipulés qu'à travers push/popGLStates à partir du moment où la RenderWindow est active ?
Ben, dans ta fonction, tu fais bien des draw non ? :P

Oui et non !

Oui en effet avec mes NinePatch je fais des draw ! Mais pour l'exemple de code minimal pour reproduire le problème je ne fais strictement rien de tel dans la fonction getTextureFromRenderTexture ^^ !

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML 2.0] 9-slice scaling - souci de RenderTexture
« Réponse #27 le: Mai 11, 2013, 06:48:36 pm »
Effectivement.

Mais dans ce cas de figure il faut aussi appeler ces fonctions ;)
Laurent Gomila - SFML developer

 

anything