Question

J'ai lu quelque part que, lors du rendu de nombreux objets 3D, il était possible de les fusionner pour former un maillage géant, de sorte qu'un seul appel de dessin soit effectué. Laissons donc le "guillemet:" le GPU faire sa magie ", tandis que le processeur est libre pour les autres appels que draw.

À ma question, est-ce que cela serait réalisable dans un environnement 2D avec la performance en tête?

Par exemple, supposons que nous ayons un système de vignettes simple et qu'au lieu de faire un appel de tirage pour chaque vignette en vue, on devrait plutôt fusionner toutes les vignettes pour former un grand sprite, puis appeler un tirage. dessus.

Toute compréhension de la question - conseils, liens ou autres - est grandement appréciée, car je n’ai aucune expérience en performances graphiques.

Modifier: Désolé pour ma piètre explication. Je crée un moteur de tuiles pour un usage personnel et je souhaite qu'il soit aussi polyvalent que possible. Par conséquent, je veux optimiser au cas où je devrais dessiner beaucoup de carreaux dans un proche avenir.

Je utilise une feuille de mosaïque, mais ce que je voulais dire par-dessus la question est de savoir si la fusion de toutes les mosaïques à tirer de la feuille dans une nouvelle Texture2D gagnera en performance. Par exemple:

Nous avons des carreaux de 128x72 à dessiner à l’écran. Au lieu de parcourir en boucle toutes les tuiles et d'appeler Draw pour chaque tuile à dessiner, nous fusionnons toutes les tuiles dans une nouvelle image-objet de 1280x720 et la dessinons. Ainsi, la méthode draw () ne sera appelée qu'une fois par image . Ma question était de savoir si cela améliorerait les performances, tout comme la fusion d'objets 3D en un seul maillage lors de la réalisation de la 3D.

Parce que l’information que j’ai collectée est que l’appel de draw () est une performance et doit être appelé le moins possible. Quelqu'un à confirmer ou à nier? :)

Était-ce utile?

La solution

Je n'ai aucune expérience de XNA et de 3D, mais je vais vous donner quelques conseils pour les jeux en 2D. J'ai passé quelque temps à créer un moteur de tuiles dans XNA au début de cette année et je me demandais la même chose. Je pense que la réponse courte est oui, combiner vos tuiles dans un sprite plus grand est une bonne idée si vous vous souciez de la performance. Toutefois, la réponse est beaucoup plus longue si vous êtes intéressé.

En général, en ce qui concerne l'optimisation des performances, la réponse est presque toujours: "ne le faites pas." Si vous êtes certain que vous devez optimiser les performances, la réponse suivante est presque toujours "Ne le faites pas encore". Enfin, si vous essayez d’optimiser les performances, le plus important est d’utiliser des points de repère pour collecter des mesures précises des performances avant et après les modifications. Sans cela, vous ne savez pas si vous réussissez!

Maintenant, plus en rapport avec les jeux 2D, j’ai appris que les performances de mon moteur de tuiles étaient bien meilleures, moins j’ai changé de texture. Par exemple, disons que j'ai une tuile d'herbe et une tuile de gravier. S'il s'agit de deux textures distinctes en mémoire et que je dessine une tuile d'herbe, puis une tuile de gravier, puis une tuile d'herbe à l'écran, le processeur graphique charge la texture de l'herbe, puis la désactive pour charger la texture de gravier, puis changez la la texture de l'herbe pour dessiner une autre dalle d'herbe. Cela tue la performance très rapidement! Le moyen le plus simple de contourner ce problème est d’avoir une feuille de sprite dans laquelle vous placerez vos tuiles d’herbe et de gravier dans une seule texture, et il vous suffira de dire à SpriteBatch de dessiner à partir d’une zone différente sur la même texture à chaque fois.

Une autre chose à considérer est le nombre de tuiles que vous allez dessiner à la fois sur l’écran. Je ne me souviens pas précisément, mais je dessinais des milliers de carreaux à la fois (dans une vue agrandie). J'ai remarqué que lorsque j'ai utilisé des carreaux plus grands et que j'en ai dessiné moins, comme vous le suggérez dans votre question, les performances se sont également améliorées. Cela n’a cependant pas été aussi important que ce que j’ai décrit dans le dernier paragraphe, et je vous encourage néanmoins à mesurer les changements de performances résultant de différentes implémentations. De plus, si vous ne dessinez que quelques dizaines ou quelques centaines de tuiles, il ne vaut peut-être pas la peine d'essayer de l'optimiser pour le moment (voir le deuxième paragraphe).

Juste pour que vous sachiez que je n'invente pas tout ça, voici un lien vers un article de Shawn Hargreaves sur l'échange de texture, les feuilles de style, etc. Il y a probablement de meilleurs articles sur les forums XNA ainsi que sur le blog de Shawn Hargreaves si vous recherchez sur le sujet.

http://forums.xna.com/forums/p/ 24254 / 131437.aspx # 131437

Mise à jour:

Puisque vous avez mis à jour votre question, laissez-moi mettre à jour mon message. J'ai décidé de simplement analyser quelques exemples pour vous donner une idée de ce que pourraient être les différences de performances. Dans ma fonction Draw (), j'ai les éléments suivants:

        GraphicsDevice.Clear(Color.CornflowerBlue);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        spriteBatch.Begin();

#if !DEBUG
        spriteBatch.Draw(tex, new Rectangle(0, 0, 
                         GraphicsDevice.Viewport.Width,
                         GraphicsDevice.Viewport.Height), 
                         Color.White);            
#else
        for (int i = 0; i < 128; i++)
            for (int j = 0; j < 72; j++)
            {
                Rectangle r = new Rectangle(i * 10, j * 10, 10, 10);
                spriteBatch.Draw(tex, r, r, Color.White);
            }
#endif
        spriteBatch.End();

        sw.Stop();

        if (draws > 60)
        {
            numTicks += sw.ElapsedTicks;
        }
        draws++;

        if (draws % 100 == 0)
            Console.WriteLine("avg ticks: " + numTicks / (draws - 60));

        base.Draw(gameTime);

Supprimez simplement le point d'exclamation dans le champ "#if! DEBUG". instruction pour basculer entre les deux méthodes. J'ai sauté les 60 premiers tirages parce qu'ils incluaient une configuration initiale (je ne savais pas trop quoi) et faussaient les moyennes. J'ai téléchargé une image 1280x720 et, pour le cas de test, je l'ai dessiné une fois. Pour le test de fond, j'ai dessiné l'image source unique en mosaïques, 128x72 comme vous l'avez demandé dans votre question. Voici les résultats.

Dessin d'une image:

avg ticks: 68566
avg ticks: 73668
avg ticks: 82659
avg ticks: 81654
avg ticks: 81104
avg ticks: 84664
avg ticks: 86626
avg ticks: 88211
avg ticks: 87677
avg ticks: 86694
avg ticks: 86713
avg ticks: 88116
avg ticks: 89380
avg ticks: 92158

Dessin des mosaïques 128x72:

avg ticks: 7902592
avg ticks: 8052819
avg ticks: 8012696
avg ticks: 8008819
avg ticks: 7985545
avg ticks: 8028217
avg ticks: 8046837
avg ticks: 8291755
avg ticks: 8309384
avg ticks: 8336120
avg ticks: 8320260
avg ticks: 8322150
avg ticks: 8381845
avg ticks: 8364629

Comme vous pouvez le constater, il existe une différence de plusieurs ordres de grandeur, elle est donc très importante. C'est assez simple de tester ce genre de choses, et je vous recommanderais d'exécuter vos propres tests afin que votre configuration spécifique prenne en compte quelque chose que j'ai peut-être manqué.

Autres conseils

Moins la carte graphique doit changer de texture, meilleures sont les performances. Vous pouvez trier les textures dans la méthode SpriteBatch.Begin () si vous le souhaitez afin que la carte graphique permute les textures le moins possible.

Je mets mes tuiles / sprites dans des feuilles lorsque cela a du sens. Par exemple, un caractère peut être dans une feuille et une couche de carreaux peut être dans la même feuille. Cela a plutôt bien fonctionné jusqu'à présent.

Je dirais que n'optimisez pas avant d'avoir à le faire. Si vos jeux tournent assez vite, pourquoi ne pas vous préoccuper d'optimisation?

  

Rectangle r = nouveau Rectangle (i * 10, j * 10, 10, 10);

La création de nombreux nouveaux objets appellera la récupération de place qui peut beaucoup ralentir! vous ne devez pas allouer de nouveaux objets dans de grandes boucles:

La performance n’est pas un impératif universel ni un commandement de Dieu; c'est un moyen d'atteindre un but. Si vos performances sont suffisamment performantes, vous n’avez littéralement rien à gagner à l’améliorer. Maintenir " la meilleure performance possible à tout moment " est la définition de l'optimisation prématurée, et cela causera plus de maux de tête qu'il n'en empêche.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top