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 :

Programme OpenGL trop lent..


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    46
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 46
    Par défaut Programme OpenGL trop lent..
    Je développe un moteur 3D, basé sur OpenGL. Tout fonctionne cependant c'est lent, pour seulement 2000 polygones les FPS sont divisés par 10.

    Voilà directement mes codes.

    Ce qui est utilisé (en gros) dans mes structure:
    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
     
    typedef struct ge_Vertex {
    	float u, v; //Coordonnées de texture
    	unsigned int color; //couleur, format 0xAABBGGRR
    	float nx, ny, nz; //vecteur normal
    	float x, y, z; //position dans l'espace
    } ge_Vertex;
     
    typedef struct ge_Object {
    	ge_Vertex* verts; //tableau des vertices
    	int nVerts; //nombre de vertices
    	bool lighted; //indique s affecté par l'éclairage
    	ge_Image* texture; //la texture
    	u32 vertex_buffer; //l'ID OpenGL du VBO
    	/*......*/
    } ge_Object;
     
    typedef struct ge_Scene {
    	ge_Object** objs; //tableaux de pointeurs vers les objets
    	int nObjs; //nombre d'objets
    	/*......*/
    	ge_Light* lights[8]; //tableaux de pointeurs vers les lumières
    	int nLights; //nombre de lumières
    } ge_Scene;
     
    typedef struct ge_Image {
    	/*......*/
    	u32 glId; //ID OpenGL de texture
    } ge_Image;
    Affichage objet :
    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
     
    void DrawObject(ge_Object* obj){
    	//J'utilise les VBOs pour plus de vitesse
    	//activation du VBO
    	glBindBuffer(GL_ARRAY_BUFFER, obj->vertex_buffer);
     
    	void* vertices = BUFFER_OFFSET(24);
    	void* colors = BUFFER_OFFSET(8);
    	void* normals = BUFFER_OFFSET(12);
    	void* tex_coords = BUFFER_OFFSET(0);
    	glVertexPointer(3, GL_FLOAT, sizeof(ge_Vertex), vertices);
    	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ge_Vertex), colors);
    	glNormalPointer(GL_FLOAT, sizeof(ge_Vertex), normals);
    	glTexCoordPointer(2, GL_FLOAT, sizeof(ge_Vertex), tex_coords);
     
    	//plus besoins du VBO
    	glBindBuffer(GL_ARRAY_BUFFER, 0);
     
     
    	//pour savoir si il a une texture
    	textured = obj->texture?true:false;
    	//si oui, la binder
    	if(textured)glBindTexture(GL_TEXTURE_2D, obj->texture->glId);
     
    	//j'utilise les shaders (ils ne ralentissent pas le prog, au contraire, c'est testé)
    	glUniform1i(location_textured, textured);
    	glUniform1i(location_lighted, obj->lighted);
     
    	//Affichage
    	glDrawArrays(GL_TRIANGLES, 0, obj->nVerts);
    }

    Affichage scène :
    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
     
    void ge3dDrawScene(ge_Scene* scene){
    	// Paramétrages des lumières
    	// ligths_type[] est passé au shader
    	int i = 0;
    	for(i=0; i<scene->nLights; i++){
    		ligths_type[i] = scene->lights[i]->type * scene->lights[i]->used;
    		//*scene->lights[i]->used je fais cela plutot qu'un if(scene->lights[i]->used) qui est plus consommateur
     
    		//Tout ce bordel pour quelques positions
    		glLightfv(GL_LIGHT0+i, GL_POSITION, &scene->lights[i]->x);
    		if(scene->lights[i]->type == GE_LIGHT_TYPE_SPOT){
    			glLightfv(GL_LIGHT0+i, GL_SPOT_DIRECTION, &scene->lights[i]->cX);
    		}
    	}
     
    	//Passage de variables au shader
    	if(shader_supported && shaderId){
    		glUniform1iv(location_ligths_type, GL_MAX_LIGHTS, ligths_type);
    		glUniform1i(location_count_lights, scene->nLights);
    	}
     
    	//Affichage des objets, un à un !
    	for(i=0; i<scene->nObjs; i++){
    		//Paramétrage du matériau
    		glMaterialfv(GL_FRONT, GL_AMBIENT, scene->objs[i]->material.ambient);
    		glMaterialfv(GL_FRONT, GL_DIFFUSE, scene->objs[i]->material.diffuse);
    		glMaterialfv(GL_FRONT, GL_SPECULAR, scene->objs[i]->material.specular);
    		//on affiche enfin l'objet...
    		DrawObject(scene->objs[i]);
    	}
    }
    Si il y a moyen d'améliorer ça... je pense que ça ne tient que dans un soucis d'organisation...
    Merci !



    Je passe à environ 1000 FPS pour seulement 1701 polygones faits de 17 objets, en résolution 1680x1050. Sur le PC de mon ami (un portable) ça tourne autour des 18 FPS....
    Ma config: Athlon X2 @3Ghz, ATI HD Radeon 4870


    EDIT: Pour ceux qui voudraient tester (Z,Q,S,D pour se déplacer, E pour la lampe torche)

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 141
    Billets dans le blog
    150
    Par défaut
    Bonjour,

    Je pense ( mais je ne suis pas sur à 100% ) que pour optimiser, il faut que tu fasse le dessin de tout tes objets en même temps.
    Je m'explique:

    Avec le morceau de code que tu nous montre, on voit que tu apelle ceci:
    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
     
    	glBindBuffer(GL_ARRAY_BUFFER, obj->vertex_buffer);
     
    	void* vertices = BUFFER_OFFSET(24);
    	void* colors = BUFFER_OFFSET(8);
    	void* normals = BUFFER_OFFSET(12);
    	void* tex_coords = BUFFER_OFFSET(0);
    	glVertexPointer(3, GL_FLOAT, sizeof(ge_Vertex), vertices);
    	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ge_Vertex), colors);
    	glNormalPointer(GL_FLOAT, sizeof(ge_Vertex), normals);
    	glTexCoordPointer(2, GL_FLOAT, sizeof(ge_Vertex), tex_coords);
     
    	//plus besoins du VBO
    	glBindBuffer(GL_ARRAY_BUFFER, 0);
     
     
    	//pour savoir si il a une texture
    	textured = obj->texture?true:false;
    	//si oui, la binder
    	if(textured)glBindTexture(GL_TEXTURE_2D, obj->texture->glId);
     
    	//j'utilise les shaders (ils ne ralentissent pas le prog, au contraire, c'est testé)
    	glUniform1i(location_textured, textured);
    	glUniform1i(location_lighted, obj->lighted);
     
    	//Affichage
    	glDrawArrays(GL_TRIANGLES, 0, obj->nVerts);
    }
    Pour tout les objets.
    C'est la qu'est le problème, je pense.
    Pour optimiser, il faut que par boucle d'affichage tu apelle qu'une seule fois cette partie, et qu'elle prenne en compte directement tous les objets de la scène.
    Soit ( pour au moins les fonctions suivantes ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    	glVertexPointer(3, GL_FLOAT, sizeof(ge_Vertex), vertices);
    	glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ge_Vertex), colors);
    	glNormalPointer(GL_FLOAT, sizeof(ge_Vertex), normals);
    	glTexCoordPointer(2, GL_FLOAT, sizeof(ge_Vertex), tex_coords);
    Au lieu de donner les informations d'un objet par un objet, il faut que tu donne un tableau des vertex ( et autres couleurs, normales ... ) de tous les objets d'un coup. Les informations doivent se suivre genre:
    [ Vertex Objet 1 ][ Vertex Objet 2 ][ Vertex Objet 3 ] ...
    Ainsi OpenGL prendra en compte tout se tableau d'un coup et tu gagnera en temps ( car là si je me trompe pas, tu perd en communicant beaucoup entre le CPU et le GPU )

    Voilà, en espérant ne pas me planter
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    46
    Détails du profil
    Informations personnelles :
    Âge : 31
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 46
    Par défaut
    Merci de ton aide, à vue d'œil ça doit vraiment accélérer je pense.



    EDIT: A mon grand mécontentement cela ne fait gagner qu'entre 10 et 20 FPS...

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 141
    Billets dans le blog
    150
    Par défaut
    Je dirai qu'un gain de 10 à 20 FPS est déjà assez bien :p
    Sinon, tu peux essayer une technique de frustrum culling ( affichage de seul les objets vus dans la scène final )
    Enfin dans le cas, ou dans ta scène, il y a des objets derrière toit.

    Sinon y a aussi le GlHint qui peut permettre de gagner ( parait que le GL_NICEST est gourmand de mémoire )
    Il y a aussi d'autre flags qui sont à changer ...
    Dernière solution, fait un profilage de ton code pour savoir ou tu bouffe du temps ( partie critique )
    ( Je crois qu'il y a un tuto sur le site ... explication avec valgrind et VS )
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Par défaut
    tu utilise des lumière opengl, c'est mal

    en fait, plus personne n'utilise de lumière opengl, car leur rendu est pourri (éclairage par vertex), mais surtout, des qu'on utilise plusieurs lumières, c'est ultra lent (essaye la même scène avec une seul lumière et 8x plus de polygones pour voir)
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  6. #6
    Membre chevronné
    Inscrit en
    Février 2008
    Messages
    413
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Février 2008
    Messages : 413
    Par défaut
    Salut,

    pour la lumière bafman, bien d'accord que celles du pipeline fixe sont ultra laides et cie, mais si il n'utilise pas de shaders il n'y pas trop le choix...

    sinon, d'une maniere générale tu peux aussi verifier si tu as bcp de changement d'états (glenable / gldisable), et essayer de grouper les objets pour minimiser ces changements.

    Par exemple:
    1 - tous ceux qui sont éclairés et texturés
    2 - tous ceux qui sont éclairés
    3 - ce qui n'est pas éclairé (par exemple du texte...)

    Un autre truc que j'ai essayé récemment et qui marche vraiment pas mal:
    plutôt que de changer d'état 2 fois (activer un truc puis le désactiver), il vaut mieux sauvegarder l'etat correspondant, le changer, dessiner puis faire un pop des attributs avant la suite du dessin, ca va bcp plus vite. Un exemple:

    plutôt que:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    glEnable(GL_BLEND);	
    glEnable(GL_TEXTURE_2D);
     
    ...dessin....
     
    glDisable(GL_BLEND)
    glDisable(GL_TEXTURE_2D)
     
    ...suite du dessin...
    essaie ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    glPushAttrib(GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT);	
    glEnable(GL_BLEND);	
    glEnable(GL_TEXTURE_2D);
     
    ...dessin...
     
    glPopAttrib
     
    ..suite du dessin...();

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/10/2013, 22h35
  2. accélération programme trop lent
    Par djocin dans le forum Fortran
    Réponses: 6
    Dernier message: 01/07/2009, 12h30
  3. Programme trop lent
    Par subversa dans le forum DirectX
    Réponses: 7
    Dernier message: 18/11/2008, 18h52
  4. OpenGL trop lent pour la 2D !!!
    Par kagemusha dans le forum OpenGL
    Réponses: 17
    Dernier message: 14/12/2005, 11h06
  5. aide en programmation opengl:maillage 3d de visage
    Par lisser dans le forum OpenGL
    Réponses: 4
    Dernier message: 14/05/2004, 23h25

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