Grand tampon de vertex contre plusieurs appels de tirage

14

Je viens de commencer avec OpenGL et j'essaie de l'utiliser pour créer un jeu 2D. Dans ce jeu, j'ai une grille hexagonale composée d'une très grande variété d'hexagones de couleurs différentes. En tant que programmeur débutant OpenGL, je vois deux façons de dessiner cette grille:

  1. Utilisation d'un tampon de sommet avec les données d'un seul hexagone, puis utilisation d'une valeur de décalage uniforme et itération sur le processeur pour dessiner plusieurs fois le même programme jusqu'à ce que j'ai une grille.
  2. Création d'un très grand tampon de sommets pré-calculé singulier qui dessine tous les hexagones en un seul appel.

Quelle est la méthode la plus efficace? Existe-t-il une meilleure façon de le faire?

Alexis King
la source
Votre tampon de vertex pré-calculé n'a besoin que de s'étendre au-delà de l'écran d'un hexagone, vous pouvez ensuite le simuler en faisant défiler doucement jusqu'à ce que vous atteigniez un hexagone complet, puis en "déformant" en arrière, comme pour les couleurs de ce scénario, vous pouvez garder un Texture 2D sur le GPU, lisez-la dans le vertex shader et interpolez-la à plat dans le fragment shader.
MickLH
Les passes font généralement référence à une situation où une opération de rendu dépend des résultats d'une opération antérieure. Ce que vous demandez dans cette question est en fait lié à la réduction du nombre d'appels de tirage au sein d'un seul passage. Je sais que cela semble pédant, mais il est très important de comprendre la différence sinon les algorithmes multi-passes n'auront pas beaucoup de sens;)
Andon M. Coleman
@ AndonM.Coleman Hmm, merci, je ne suis clairement pas familier avec la terminologie graphique. Alors, dans ce cas, comment pourrais-je le décrire? Plusieurs appels de shader / programme?
Alexis King
Vous pouvez immédiatement dire qu'il s'agit d'un algorithme à passage unique car il n'y a pas de dépendance à l'ordre; vous pouvez dessiner ces hexagones dans n'importe quel ordre et toujours obtenir le même résultat. Vous pouvez prendre plusieurs appels de dessin pour fournir à OpenGL les données nécessaires à leur rendu, mais OpenGL est effectivement libre de les dessiner tous en parallèle car il n'y a pas de dépendances. S'il s'agissait de passes multiples , l'hexagone B pourrait nécessiter le résultat de l'hexagone A avant de pouvoir être dessiné, ou vous pourriez avoir besoin de dessiner le même hexagone plusieurs fois et de combiner le résultat.
Andon M. Coleman

Réponses:

9

Il existe en effet plusieurs façons de réaliser une telle grille.

Le moyen le plus efficace serait l'instanciation. De cette façon, vous ne créez votre hexagone qu'une seule fois dans un VBO et le restituez cent, mille ou un million de fois. Vous pouvez le faire manuellement en utilisant des shaders avec des uniformes comme vous l'avez dit au point 1, mais il y a aussi une fonctionnalité OpenGL intégrée pour cela. Pour cela, jetez un œil à glDrawElementsInstanced .

Notez que l'instanciation n'est plus rapide que les autres méthodes si vous dessinez plus d'une certaine quantité d'objets instanciés. Par exemple, dessiner 300 peut être plus rapide en utilisant 1 gros VBO, mais dessiner 2 millions peut être plus rapide si vous utilisez le rendu instancié.

Si vous utilisez le rendu instancié, vous pouvez envoyer des données par objet à l'aide des diviseurs d'attribut . Dans votre cas, vous souhaitez envoyer la position et la couleur.

Un bon tutoriel sur le rendu instancié: cliquez sur

La meilleure façon est d'essayer les deux méthodes et de vérifier le nombre de millisecondes nécessaires pour dessiner 1 image. De cette façon, vous apprenez également les deux façons, ce qui est toujours bon.

Notez également que le rendu instancié est une fonctionnalité OpenGL moderne et que vous devrez utiliser des shaders pour l'utiliser. Mais il est toujours préférable de l'apprendre correctement depuis le début.

Basaa
la source
2
L'instanciation n'est pas nécessairement la plus efficace; dans de nombreuses implémentations dont j'ai vu des profils, le support d'instanciation a été cloué pour la conformité mais plus lent que le dessin individuel de nombreux objets (en effet, il s'agissait probablement d'une boucle mal implémentée dans le pilote faisant exactement cela). C'est une option, et une bonne, mais il faut faire attention à profiler et tester sur le système d'exploitation / matériel cible avant de faire des hypothèses sur "le plus efficace".
Sean Middleditch
D'accord. J'ai vu différentes performances sur Windows / Linux et Ati / nVidia par exemple. Merci pour l'ajout.
Basaa
1
En réalité. Si vous dessinez plusieurs maillages combinés dans un seul vbo (qui partagent le même espace). Aucune instanciation ne pourrait être plus rapide. Le problème avec l'instanciation est: les sommets ne sont pas des instances croisées calculées parallèlement. Il élimine seulement la synchronisation / drawcall gpu / cpu / gpu. Il est donc plus rapide de dessiner un tampon de vertex contenant 1000 sphères que de dessiner 1000 sphères avec une instanciation matérielle. (pas d'élimination du tronc de cône / optimisation des détails de la distance des objets impliquée)
Jeroen van Langen
3

La méthode 1 est plus simple à coder et convient parfaitement tant que vous n'avez pas trop d'hexagones en vue à la fois. Vous voudrez peut-être vous en tenir à cela puisque vous êtes nouveau sur OpenGL, pour éviter de mettre trop de complexité dans votre assiette à la fois.

S'il y a un grand nombre d'hexagones (comme plusieurs centaines ou plus d'un millier) en vue à la fois, une méthode de surcharge moindre serait nécessaire pour éviter la surcharge CPU de faire autant de tirages individuels. La méthode 2 fonctionnerait pour cela, ou mieux encore, utiliser l'instanciation. Je m'attends à ce que l'instanciation soit plus rapide que la méthode 2, ou certainement pas pire, car vous n'avez qu'à mettre à jour un tampon de données par instance plutôt qu'un tampon (beaucoup plus grand) de données de vertex pour toutes les instances.

Nathan Reed
la source