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 :

vertex arrays ~ mode immédiat


Sujet :

OpenGL

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut vertex arrays ~ mode immédiat
    Bonjour, je suis en train de coder un moteur de particule CPU. Pour l'instant au niveau rendu, j'ai fait qu'une implémentation openGL. Au début je rendais les particules en mode immediat. Puis je me suis dis que je pourrais sans doute améliorer les perf en les rendant a l'aide de vertex arrays. J'ai donc fait une implémentation de mes renderers en vertex arrays. Mais niveau perf, ca n'a rien changé (6 à 7 millions particules / s avec des primitives simples (GL_LINES et GL_POINTS)).

    Evidemment, je dois updater les paramètres de mes vertices a chaque frame donc en fait le seul truc que ca change entre le mode immediat et les vertex arrays c'est que ca réduit considérablement le nombre d'appels au fonctions openGL. Comme ca prend quand meme plus de mémoire les vertex arrays (les tableaux de paramètre des vertices), je vais sans doute rester au mode immédiat. Est ce que c'est normal que je n'ai pas du tout d'amélioration des performances ? Et du coup est ce qu'en allant voir du coté des VBO, ca pourrait améliorer quelque chose ?

    En fait je pense que c'est clairement mon CPU qui limite. Est ce que la différence pourrait être notable sur un PC avec un bon CPU et une carte graphique moins bien ?

  2. #2
    Membre habitué
    Inscrit en
    Juin 2008
    Messages
    162
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 162
    Points : 172
    Points
    172
    Par défaut
    A ta place je testerai avec 10 000 particules et je chercherai a optimiser le FPS plus tot que de mettre des millions de particules.

    Pour les VBO je ne vois pas trop d'interret ... en tout cas pas pour des particules dynamiques car de tt facon tu vas transferer tout les données à chaque fois.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    C'est ce que je fais, je teste avec 10000 à 30000 particules et j'obtiens de 750 fps à 250 fps environ. Mon moteur étant O(n) ca me fait du 7 millions de particules / s.

    Mais en fait j'ai remarqué que je perdais plutôt en performance avec les vertex array (je passe environ à 5 à 6 millions de particules / s). Rien d'énorme mais un peu.

    Je met des bouts de code :

    Voila le code du rendererer openGL pour les lines version mode immediat :

    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
     
    	bool GLLineRenderer::begin(const Group& group) const
    	{
    		initBlending();
     
    		glLineWidth(width);
    		if (antialiasing)
    			glEnable(GL_LINE_SMOOTH);
    		else
    			glDisable(GL_LINE_SMOOTH);
     
    		glBegin(GL_LINES);
     
    		return true;
    	}
     
    	void GLLineRenderer::render(const Particle& particle) const
    	{
    		glColor4f(particle.getParamValue(INDEX_RED),
    			particle.getParamValue(INDEX_GREEN),
    			particle.getParamValue(INDEX_BLUE),
    			particle.getParamValue(INDEX_ALPHA));
     
    		glVertex3f(particle.position.x,
    			particle.position.y,
    			particle.position.z);
     
    		glVertex3f(particle.position.x + particle.velocity.x * length,
    			particle.position.y + particle.velocity.y * length,
    			particle.position.z + particle.velocity.z * length);
    	}
     
    	void GLLineRenderer::end(const Group& group) const
    	{
    		glEnd();
    	}
    et voila version vertex arrays :

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    	bool GLLineRendererVA::begin(const Group& group) const
    	{
    		if (group.getNbParticles() > nbVertices >> 1)
    			return false;
     
    		vertexIterator = vertexArray;
    		colorIterator = colorArray;
     
    		return true;
    	}
     
    	void GLLineRendererVA::render(const Particle& particle) const
    	{
    		*colorIterator++ = particle.getParamValue(INDEX_RED);
    		*colorIterator++ = particle.getParamValue(INDEX_GREEN);
    		*colorIterator++ = particle.getParamValue(INDEX_BLUE);
    		*colorIterator++ = particle.getParamValue(INDEX_ALPHA);
     
    		*colorIterator++ = particle.getParamValue(INDEX_RED);
    		*colorIterator++ = particle.getParamValue(INDEX_GREEN);
    		*colorIterator++ = particle.getParamValue(INDEX_BLUE);
    		*colorIterator++ = particle.getParamValue(INDEX_ALPHA);
     
    		*vertexIterator++ = particle.position.x;
    		*vertexIterator++ = particle.position.y;
    		*vertexIterator++ = particle.position.z;
     
    		*vertexIterator++ = particle.position.x + particle.velocity.x * length;
    		*vertexIterator++ = particle.position.y + particle.velocity.y * length;
    		*vertexIterator++ = particle.position.z + particle.velocity.z * length;
    	}
     
    	void GLLineRendererVA::end(const Group& group) const
    	{
    		initBlending();
     
    		glLineWidth(width);
    		if (antialiasing)
    			glEnable(GL_LINE_SMOOTH);
    		else
    			glDisable(GL_LINE_SMOOTH);
     
    		glEnableClientState(GL_VERTEX_ARRAY);
    		glEnableClientState(GL_COLOR_ARRAY);
     
    		glColorPointer(4,GL_FLOAT,0,colorArray);
    		glVertexPointer(3,GL_FLOAT,0,vertexArray);
     
    		glDrawArrays(GL_LINES,0,group.getNbParticles() << 1);
     
    		glDisableClientState(GL_VERTEX_ARRAY);
    		glDisableClientState(GL_COLOR_ARRAY);
    	}
    En fait il y a plus d'opération avec les vertex array puisque qu'on est obligé d'avoir une couleur par sommet alors qu'avec le mode imémdiat je les sette par primitive. du coup pour les lignes ca fait 2 au lieu de 1 et pour les quad ca fait 4 au lieu de 1. Le tout multiplié par le nombre de particules... La perte de perf peut peut etre s'expliquer en partie avec ca. Mais je me demande si dans le cas d'un pc avec carte graphique plus limitée que le CPU ou dans le cas d'un jeu mettant plus a mal la CG, la tendance ne pourrais pas s'inversé, c'est a dire que les VA commencent a avoir de meilleur perf. Enfin j'ai codé les 2 implémentations donc autant que je garde les 2. Sinon n'y aurait il pas un autre moyen pour transférer les données à la CG qui pourrait être plus efficace dans mon cas ?

  4. #4
    Membre habitué
    Inscrit en
    Juin 2008
    Messages
    162
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 162
    Points : 172
    Points
    172
    Par défaut
    Est ce que la couleur evolue avec le temps? si non remplie une fois l'array de couleur et ne le touche plus.
    Est ce que tu alloue de la memoire à chaque frame? ou est ce que tu la vide avant de remplir (avec un memset ou autre ?) ?

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    La couleur peut ou non evoluer avec le temps. tout dépend des paramètres du modele de particule setté par l'utilisateur. En fait j'essaie de faire un moteur de particule le plus générique et paramétrable possible, donc ca a implique forcément une dégradation des perf par rapport a un moteur ultra spécialisé.

    Concernant mes tableaux : en fait ce sont des tableaux statique de la classe mère (GLRenderer) qui sont créé lors de l'init grace à un nombre de vertices max passé par l'utilisateur. Donc ce sont les même tableaux utilisé par tous les groupes de particules. Je ne les remet pas à zero, ni ne les recrée a chaque frame, je me contente de réécrire par dessus.

    Pour le tableau de texture je le remplit au début puisqu'il ne bouge pas (enfin pour mes renderer mais ca empeche du coup de créé un renderer qui va aller le modifier et ca perd donc en modularité)

    Voila comment je créé mes tableaux :

    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 GLRenderer::createBufferArrays(unsigned int maxNbVertices)
    	{
    		if (maxNbVertices == 0)
    			return;
     
    		if (nbVertices > 0)
    			disposeBufferArrays();
     
    		nbVertices = maxNbVertices;
    		vertexArray = new float[nbVertices * 3];
    		colorArray = new float[nbVertices << 2];
    		textureArray = new float[nbVertices << 1];
     
    		// initializes texture buffer
    		float t[8] = {0.0f,0.0f,1.0f,0.0f,1.0f,1.0f,0.0f,1.0f};
    		for (unsigned int i = 0; i < nbVertices << 1; ++i)
    			textureArray[i] = t[i & 7];
    	}
     
    	void GLRenderer::disposeBufferArrays()
    	{
    		delete[] vertexArray;
    		delete[] colorArray;
    		delete[] textureArray;
     
    		vertexArray = NULL;
    		colorArray = NULL;
    		textureArray = NULL;
    		nbVertices = 0;
    	}
    Donc en fait les VA sont plus lents et bouffe plus de mémoire (2 Mo en plus environ pour 60000 vertices)

    [EDIT] je viens de lire sur un autre post que le glDrawElements est asynchrone. J'imagine donc qu'il en ai de même pour le glDrawArrays... Dans ce cas, l'utilisation de tableaux statiques est dangereuse... Il faudrait multiplier le nombre de tableau par le nombre de groupe de particules a rendre, ce qui prendrai encore plus de mémoire

Discussions similaires

  1. Vertex array Vs rendu immédiat
    Par GLDavid dans le forum OpenGL
    Réponses: 3
    Dernier message: 29/05/2009, 14h12
  2. Vertex arrays
    Par goutbouyo dans le forum OpenGL
    Réponses: 9
    Dernier message: 06/01/2005, 13h11
  3. [SDL+glut] vertex array précompilés
    Par khayyam90 dans le forum OpenGL
    Réponses: 3
    Dernier message: 01/10/2004, 17h07
  4. vertex array
    Par Jbx 2.0b dans le forum OpenGL
    Réponses: 2
    Dernier message: 12/07/2004, 11h37
  5. Performance des vertex array
    Par Mathieu.J dans le forum OpenGL
    Réponses: 13
    Dernier message: 25/06/2004, 10h47

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