IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[PyOpengl] Tres tres basses performances


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Octobre 2007
    Messages
    204
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 204
    Par défaut [PyOpengl] Tres tres basses performances
    Bonjour,
    Dans le cadre de developpement de mon moteur 3D en python et opengl je fais face a un probleme tres embetant: Les performances sont tres basses(~ 20 FPS). Le moteur est encore super simple, je en fais que charger des modeles 3D d'un fichier .obj + la texture, et les afficher. J'utilise une classe VBO pour masquer les details bas niveau.
    Voici le code en question:
    la classe Mesh qui contient les vbos et les affiche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    class Mesh:
        def __init__(self, mesh_file, texture_file=None):
     
            loader = ObjLoader()
            self.vbos = loader.load(mesh_file)
            self.texture = None
            if texture_file:
                self.texture = texture.Texture(texture_file)
     
        def draw(self):
            if self.texture:
                self.texture.bind()
     
            for v in self.vbos:
                v.bind()
     
            glDrawArrays(GL_TRIANGLES, 0, len(self.vbos[0]))
     
            for v in self.vbos:
                v.unbind()
     
            if self.texture:
                self.texture.unbind()
    la classe ObjLoader qui char un fichier .obj et retourne les vbo des positions/textures/normals
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    class ObjLoader:
     
        def load(self, obj_file):
            positions = []
            normals = []
            textures = []
            faces = []
            with open(obj_file) as f:
                for line in f:
                    n = line.find('#')
                    line = line[:n].strip().split()
                    if line:
                        if line[0] == 'v':
                            positions += [map(float, line[1:4])]
                        if line[0] == 'vn':
                            normals += [map(float, line[1:4])]
                        if line[0] == 'vt':
                            textures += [map(float, line[1:3])]
                        if line and line[0] == 'f':
                            faces += \
                                map(self.parse_face, line[1:])
     
            position_vbo = vbo.PositionVBO([positions[pos] for pos, _, _ in faces])
            texture_vbo = vbo.TextureVBO([textures[tex] for _, tex, _ in faces])
            normal_vbo = vbo.NormalVBO([normals[norm] for _, _, norm in faces])
     
            return [position_vbo, texture_vbo, normal_vbo]
     
     
        def parse_face(self, vertex):
            pattern = '(?P<v>\d*)/(?P<vt>\d*)/(?P<vn>\d*)'
            r = re.match(pattern, vertex)
     
            v = r.group('v')
            vt = r.group('vt')
            vn = r.group('vn')
            if not v or not vt or not vn:
                raise ValueError, "obj file bad formatted"
     
            return map(lambda x: int(x) - 1, [v, vt, vn])
    la classe VBO

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    class VBO:
        def __init__(self, data, usage=GL_STATIC_DRAW):
            self.buffer = GL.GLuint(0)
            self.buffer = glGenBuffers(1)
            self.count = len(data)
            self.size = len(data[0])
            glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
            data = numpy.array(data, dtype=numpy.float32)
            glBufferData(GL_ARRAY_BUFFER_ARB, ADT.arrayByteCount(data), ADT.voidDataPointer(data), usage)
     
        def __del__(self):
            print 'deleting vbo'
            glDeleteBuffers(1, GL.GLuint(self.buffer))
     
        def __len__(self):
            return self.count
     
        def bind(self):
            glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
     
        def unbind(self):
            glBindBuffer(GL_ARRAY_BUFFER_ARB, self.buffer)
     
    class PositionVBO(VBO):
        def bind(self):
            VBO.bind(self)
            glVertexPointerf(None)
     
    class TextureVBO(VBO):
        def bind(self):
            VBO.bind(self)
            glTexCoordPointerf(None)
     
    class NormalVBO(VBO):
        def bind(self):
            VBO.bind(self)        
            glNormalPointerf(None)
     
    class ColorVBO(VBO):
        def bind(self):
            VBO.bind(self)
            glColorPointerf(None)
    Le code qui exploite tout cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
     
    # Initialisation d'OpenGL
    meshes = []
    for i in range(20):
        meshes +=  [Mesh('data/objs/cube.obj', 'data/textures/texture.jpg')]
     
    while True:
        # Preparation du rendu
     
        for i, m in enumerate(meshes):
            # transformer et une classe qui se charge des transformation 3d(translation + rotation)
            transformer.translate(Vector(i, 0, 0))
            m.draw()
        # Fin du rendu, on efface l'ecran

  2. #2
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    C'est tout à fait normal que tu n'es pas les même performances que les jeux vidéo en vente ... Je suis pas expert du python ni même compris tous ton code mais je sais que celui ci est un langage de haut niveau, et est donc plus lent.

    Quand tu appelles une fonction en python pour opengl, tu n'appelle pas la "vrai" immédiatement, python passe par des étapes intermédiaire ... C la le souci.

    Le python est plustôt utilisé pour programmer de petite actions dans un mondes, genre que quand tu appuis sur un interrupteur, tu lance un video etc ... Du moins, c'est ainsi que je l'utilise dans mon moteur. Tu peus en C ou C++ faire des librairies python, qui facilité énormément ce genre de chose !

    Ensuite, chargé un obj est pas le format le plus rapide à chargé vue qu'il est en ascii, renseigne toi sur le format .3ds, beaucoup plus simple et en binnaire ! Donc pas de re-interpretation asci->float.

    J'aurai tendance à dire que si tu veux gagné en performance, recode ton moteur en C ou C++ vue qu'il "est encore super simple".

    Il est evident aussi que les perf de ton jeux sont très lié avec ton matériel. Donc renseigne toi sur ton matos.

    J'espère avoir répondu à ta question.

  3. #3
    Membre éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Par défaut
    N'oublions pas que Python est un langage interprété contrairement au C ou C++ qui sont des langages compilés donc cela joue aussi dans la balance, enfin il me semble.

  4. #4
    Membre confirmé
    Inscrit en
    Octobre 2007
    Messages
    204
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 204
    Par défaut
    C'est pas vraimenet la faute a python, parce que si j'enleve la fonction glDrawArrays, je n'ai plus de lag, et j'ai des FPS bien plus eleves.
    C'est un soucis lie au VBO donc, mais je ne vais pas trop m'avancer, je suis pas expert dans la matiere.
    Je vais essayer d'utiliser le rendu directe, et si c'est jamais c'est plus rapide(ce qui est quand meme improbable), c'est clair que j'ai un probleme au niveau du code, et pas du cote de Python.
    Pour le choix du format OBJ, ca n'influe pas dans la vitesse du rendu, le chargement est fait en amont, OBJ ou 3DS ne va pas changer grand chose.

  5. #5
    Membre confirmé
    Inscrit en
    Octobre 2007
    Messages
    204
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 204
    Par défaut
    eh non, avec les glVertex c;est 6 fois plus long je me suis goure

  6. #6
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    rendu directe
    Oublie tout de suite ! C'est carrément plus lent ! En C (et donc C++), les VBO sont des modes en faite. Il faut rentré dans le mode dessin par VBO, dessiné les VBO puis sortir du mode. N'ayant pas çà dans ton code je supose que c'est automatique. Donc tu doit perdre des performance à entré - sortir du mode. Aussi, peut être que tes objets possède trop de triangles. Si on se démerde bien, en C on attend le million affiché. mais en python, cela doit être bien plus réduit.

    Au quel cas, essaye de les optimisé par GL_TRIANGLE_STRIP au lieu de GL_TRIANGLES. (c'est très complexe à prog, mais çà accélère le rendu par 3)

    Aussi, je voit ceci "len(self.vbos[0])" dans l'appel de la fonction glDrawArrays. tu devrais stoquer cette valeur, çà te permettrai d'économisé une fonction.

    Mais AuraHxC à tout de même raison glDrawArrays peut être bien plus lente que celle en C ... D'autenps plus que ton code n'est même pas compilé ... Le processeur doit "comprendre" puis l'exécute, à la volé, mais en C, tu lui fai comprendre 1 seul fois par la compilation, il te l'optimise même ! Et ensuite çà va bien plus vite !

  7. #7
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Par défaut
    Citation Envoyé par AuraHxC Voir le message
    N'oublions pas que Python est un langage interprété contrairement au C ou C++ qui sont des langages compilés donc cela joue aussi dans la balance, enfin il me semble.
    ça joue dans la balance dans le cas d'un programme qui effectue beaucoup de traitements ou bien des traitements coûteux. ici ça n'a pas l'air d'être le cas.

    faire un shmup tout simple peut très bien être fait en interprété, et avoir un fps très élevé très facilement, et même en réalisant le code qui gère les collisions de manière naïve.
    un jeux de ture simple peut aussi être fait en interprété si on utilise par exemple ODE ou Bullet (qui eux sont compilés).

    sinon si on souahite faire un jeu plus complexe et plus couteux, on peut parfois s'en tirer en restant en interprété mais en utilisant des structures ou des algo plus efficaces. si alors c'est pas possible on peut alors aussi se contenter d'identifier le goulot d'étranglement et ne réécrire en compilé que cette portion. en dernier recours si on doit entièrement basculer vers du compilé, il y a d'autres alternatives que le C. le C est plutôt bas niveau et être interompu par un segfault au milieu d'une partie n'est jamais agréable. on peut alors se tourner vers un langage tout aussi haut niveau mais qui supporte la compilation en code natif pour des perfs égales au C.

  8. #8
    Membre éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Par défaut
    Citation Envoyé par adtunum Voir le message
    ça joue dans la balance dans le cas d'un programme qui effectue beaucoup de traitements ou bien des traitements coûteux. ici ça n'a pas l'air d'être le cas.
    Oui tu as raison, je parlais en général mais c'est sur que l'interprété dans de nombreux cas est tout aussi performant.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Par défaut
    bin sinon moi non plus je ne vois pas d'erreur dans le code qui pourrait justifier de tomber à 20 fps, mais moi non plus je ne connais pas très bien Python, donc ce que je pourrais te conseiller pour réussir à t'en sortir serait de prendre une démos python+vbo toute faite fournie dans un tutorial ou bien fournie avec les sources de l'interface python-opengl et donc en partant d'une base qui marche avancer de manière incrémentale, si à un moment tu vois les perfs tomber dramatiquement à 20 fps tu verras bien quel est le dernier changement que tu as fait.

    Quand on est très avancé dans un projet on ne peut pas procéder de la sorte, mais là tu n'as que très peu de code donc ça devrait être assez facile de procéder de cette façon.

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Par défaut
    Citation Envoyé par LastSpear Voir le message
    .... mais je sais que celui ci est un langage de haut niveau, et est donc plus lent.
    Attention ! langage de haut niveau ne veut pas forcément dire lent !
    Peut-être que tu t'es juste mal exprimé, mais un débutant lisant ceci pourrait le prendre pour argent content.

    Python est lent car il est interprété.
    Cependant il existe d'autres langages aussi haut niveau et simple que Python mais que l'on compile, et qui auront des performances équivalentes au C.

    Les langages haut niveau les plus connus étant pour la plupart interprété, c'est une erreur très répandues que de penser que tous les langages haut niveau sont également interprétés, ce qui n'est bien sur pas le cas.

    Je le répète donc encore une fois pour être sûr de bien être compris, il y a des langages aussi haut niveau et simples d'usage que Python mais compilé et qui donneront des programmes aussi rapide qu'en C.

  11. #11
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 219
    Par défaut
    Intéressant !
    C'est vrai que selon moi un langage de bas niveau c'est : C, C++, Assembleur, Très rapides, donc les haut niveau était les lents ^^

    Et çà se fait des langages comme ceux ci qui se compile au lancement de l'application ? Cà m'interesse beaucoup si on peut contrôlé leur compilation et en plus fair une interface avec des class et fonctions C++.

  12. #12
    Membre éclairé Avatar de AuraHxC
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    652
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2006
    Messages : 652
    Par défaut
    Comme par exemple ce langage Haut Niveau à Prototype : http://www.lisaac.org/

Discussions similaires

  1. Taille de tableau tres tres grand (BCB6)
    Par cquadjul dans le forum C++Builder
    Réponses: 7
    Dernier message: 27/04/2006, 08h48
  2. Tres tres débutant(découverte de l'Oracle)
    Par argon dans le forum Oracle
    Réponses: 14
    Dernier message: 19/03/2006, 19h14
  3. [Compilation] Chaine string Tres tres longues
    Par Clorish dans le forum Langage
    Réponses: 9
    Dernier message: 20/07/2005, 11h20
  4. Impression très très lente avec Samba
    Par Daav dans le forum Réseau
    Réponses: 4
    Dernier message: 29/12/2004, 18h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo