Préconcepts
Ok, ce que j'ai rassemblé jusqu'à présent est le suivant:
- n'utilisez pas de pipeline fixe (obsolète ou va être obsolète)
- vbos stocke des "modèles d'objets" (n données de sommet, principalement)
- les vaos décrivent la façon dont les données sont définies de sorte que les appels de tirage sachent quelle partie de chaque vbo correspond à quel type d'informations de sommet (un vao peut faire référence à plusieurs vbos, l'inverse est un peu difficile)
- chaque appel de tirage envoie également des données de sommet aux shaders
Comment je vois la 3D (facultatif)
Compte tenu de ces informations, je peux voir à quel point dessiner des objets 3D complexes est très agréable avec OpenGL moderne. Vous chargez essentiellement un tas de modèles d'objets (probablement à partir de Blender ou d'un autre logiciel similaire) dans des VBO avec des coordonnées locales, puis vous fournissez simplement pour chaque instance d'un objet un paramètre de shader différent (décalage) pour dessiner dans l'espace mondial.
Problème / question
En 2D, cependant, les problèmes et les priorités sont complètement différents. Vous ne dessinez pas beaucoup d'objets complexes, vous n'avez pas besoin de matrices de projection compliquées et ainsi de suite et les shaders sont beaucoup plus simples.
Quelle serait la meilleure façon de dessiner des géométries changeantes fréquemment (vraiment fréquemment, essentiellement chaque image) avec OpenGL moderne?
Dans le paragraphe suivant, vous pouvez voir quelques idées de problèmes (le problème des cercles et des rectangles), qui identifient mieux le type de changements qui m'intéressent.
Mes tentatives (facultatif)
J'ai donc commencé à réfléchir à la façon dont je traiterais le dessin d'une géométrie 2D de base à l'écran:
- un carré: charger un
[(1, 0), (1, 1), (0, 1), (0, 0)]
VBO pour la géométrie d'un carré dans l'espace local, puis fournir au shader la largeur réelle du carré et les coordonnées du monde et les informations de couleur
refroidit, semble facile. Passons à un cercle:
- un cercle: éventail en triangle avec ... eh. quelle précision (nombre de sommets)? pour les petits cercles, la précision doit être petite et pour les cercles de bogues, la précision doit être élevée. Il est clair que le chargement de 1 VBO ne peut pas convenir à tous les cas. Que faire si j'ai besoin d'ajouter de la précision car un cercle est redimensionné pour être plus grand?
Moins cool. Passons à quelque chose d'un peu plus facile, un rectangle:
- un rectangle: hein. il n'y a pas de "géométrie rectangle générale". Vous avez juste une proportion largeur / hauteur et c'est tout, mais chaque rectangle est probablement différent si la taille change.
Comme vous pouvez le voir, les choses se dégradent à partir de là. Surtout avec des polygones complexes et ainsi de suite.
Aucune politique de code: P
J'ai juste besoin d'un aperçu de l'idée, aucun code n'est nécessaire, en particulier du code C ou C ++. Dites simplement des trucs comme: "faire un VBO avec ces données de sommet, puis le lier, ...".
Réponses:
Votre principale question semble être:
Dans la plupart des cas, il n'y a pas de grande différence entre OpenGL 2D et 3D. Le pipeline graphique a cette coordonnée supplémentaire, Z, qui ne sera pas autant utilisée dans 2d, mais c'est à peu près tout.
Il existe plusieurs façons de modifier la géométrie de chaque dessin.
Vous pouvez pousser de nouveaux sommets fournis par le processeur à chaque image. (Voir /programming/14155615/opengl-updating-vertex-buffer-with-glbufferdata pour quelques notes sur la réutilisation des tampons.)
Vous pouvez dessiner différentes parties d'un tampon existant avec
glDrawArrays(mode, first, count)
. Si l'animation est en boucle, vous pouvez peut-être placer les images précalculées avec les différentes listes de sommets dans un grand tampon et dessiner la partie appropriée du tampon à chaque image.Vous pouvez influencer la liste des sommets avec d'autres données, comme un tableau uniforme ou une texture. Dans votre vertex shader, lisez ces données et appliquez-les de manière appropriée. Ce ne sont que d'autres idiomes pour présenter des données au GPU, et il n'y aura probablement pas beaucoup de différence de performances.
Si vous avez plusieurs instances de la même géométrie (éventuellement influencées par des attributs), cela
glDrawElementsInstanced()
peut être utileVous pouvez influencer la liste des sommets de manière algorithmique dans les ombrages de sommets, de géométrie ou de pavage. Si l'animation peut être décrite mathématiquement, vous pourrez peut-être conserver la même liste de sommets et modifier uniquement quelques uniformes de shader à chaque image.
Et peut-être que votre animation peut être exprimée sous forme de textures pures, avec toutes les animations effectuées pixel par pixel par le processeur, ou pré-rendues à partir du disque.
Dans l'ensemble, je dirais: «Les ordinateurs sont rapides, faites-le fonctionner de la manière la plus simple possible, ce qui est probablement en définissant de nouveaux sommets créés par le processeur à chaque image. Ensuite, voyez si cela suffit. Profilez l'utilisation de la batterie / du processeur d'abord, l'empreinte mémoire ensuite. "
Votre autre question , paraphrasée, "Quelle est une bonne façon de dessiner des cercles et des rectangles?"
Cercles.
Avec les shaders de tessellation (ou shaders de géométrie), vous pouvez rendre votre géométrie dynamique.
Vous pouvez dessiner des carrés, et dans votre shader de fragment uniquement opaque (alpha = 1.0) dans un rayon, et transparent (alpha = 0.0) en dehors du rayon. Ensuite, c'est pixel parfait à chaque fois. (Faites vos sommets carrés -1 à +1, et dans le shader de fragment quelque chose comme,.
outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;
Pourrait également lisser un peu le bord, ce serait bien là ...)Vous pouvez simplement toujours utiliser, par exemple, un ventilateur de 120 triangles. Probablement assez bien.
Rectangles.
la source
Je ne peux pas dire que je suis un expert de ce sujet, et dans mon (mes) projet (s) de jeu, je me suis concentré davantage sur le côté 3D, donc mon côté 2D est assez simple en utilisant généralement des choses faites pour le côté 3D; et évidemment, ma perspective est du côté du jeu, donc mes graphiques 2D sont plus sur le blitting des sprites que sur la géométrie. De ce point de vue,
1) Les carrés et les rectangles sont assez faciles. Je n'ai qu'une seule boîte 1x1 dans un VBO que j'utilise pour tout blit. Je passe des matrices MVP au shader avec cette "boîte d'unité", et je l'ai combinée avec une mise à l'échelle supplémentaire pour mettre la boîte à l'échelle aux bonnes dimensions - comme vous le savez, vous pouvez avoir différentes échelles x et y.
Pour mes besoins, j'ai pensé à passer de l'utilisation d'une "boîte d'unité" à une sorte de moteur de particules pour blitter des sprites 2D, mais c'est une autre histoire.
2) Je n'ai pas beaucoup travaillé avec les cercles, j'utilise juste des VBO fixes avec un nombre spécifique de sommets. Mais je pouvais imaginer que je pouvais faire quelques ajustements de foulée pour affecter le nombre de sommets dessinés pour le cercle.
Lors de la connexion de données VBO à des attributs de shader, j'utilise glVertexAttribPointer. Il a un paramètre stride destiné à être utilisé pour les données entrelacées (que j'utilise). Mais il pourrait être possible de l'utiliser comme ceci:
... pour sélectionner chaque nième sommet du tampon, affectant ainsi le nombre de sommets dessinés pour le cercle. Je pourrais créer plusieurs VAO ayant le même VBO avec une foulée différente affectant le nombre de sommets dessinés pour le cercle. Je n'ai pas essayé ça, pensai-je.
En général, oui, travailler avec des VBO et autres rend le tweaking du côté CPU plus complexe, pourquoi j'ai étudié différentes choses pour rendre le tweaking côté GPU (shaders). Pourtant, selon cet article, l'utilisation des VBO est plus efficace sur le matériel moderne même si vous avez besoin de beaucoup d '"intervention" côté CPU:
http://www.quelsolaar.com/opengl_performance.txt
J'espère que cela vous aidera un peu à concevoir et à décider de vos directions.
la source