Jeux 2D et OpenGL moderne

10

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, ...".

Chaussure
la source
Je pense que je comprends ce que vous demandez, mais vous voudrez peut-être donner un peu plus de sens à cette question. On ne sait pas trop ce qui est demandé - ce qui est en fait une raison proche.
Lysol
@AidanMueller Je ne sais pas trop ce que vous voulez dire, mais n'hésitez pas à donner plus de direction si vous en ressentez le besoin.
Shoe
La première réponse commence actuellement en disant "Votre question principale semble être". Cela indique que ce que vous demandez n'est pas clair. Vous devriez peut-être donner un résumé de ce que vous n'avez pas besoin de savoir à la fin de votre question. C'est un Q / A après tout, pas une discussion.
Lysol
@AidanMueller Pas dans ce contexte, je crois. Il dit "Votre question principale semble être ...", puis il cite la question que j'ai postée. Ce qui indique en fait qu'il est suffisamment clair pour être cité. La phrase n'indique pas non plus que ma question n'est pas claire, mais plutôt qu'il y a une question principale et une autre question secondaire (qui est: quelle est la solution aux cas spécifiques que j'ai présentés). Je ne vois vraiment pas le problème avec ma question actuelle, et apparemment même pas les répondeurs l'ont fait car j'ai trouvé les deux réponses très utiles et pertinentes.
Shoe
Vous pouvez dessiner un cercle précis avec un fragment shader.
user253751

Réponses:

5

Votre principale question semble être:

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 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 utile

  • Vous 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.

  • Je pense que vous avez répondu à votre propre question à ce sujet. Ce que vous proposez fonctionnera bien!
david van brink
la source
Le fragment-shader / radius est assez soigné, merci. En ce qui concerne ma réponse à ma propre question, je ne pense pas comprendre ce que vous voulez dire.
Chaussure du
Oh, tout comme avec un carré, vous mentionnez de contrôler la largeur (avec un uniforme, je suppose), et vous avez écrit: "Vous avez juste une proportion largeur / hauteur et c'est tout, mais chaque rectangle est probablement différent si la taille change" . Donc, pour un rectangle, faites la même chose qu'un carré mais vous aurez besoin de 4 valeurs (x, y, w, h) au lieu de 3 (x, y, w). Ou passez (xlow, xhigh, ylow, yhigh) en quatre uniformes. Avec votre entrée (0,0) à (1,1), cela suffit pour que le Vertex Shader fasse ce dont il a besoin.
david van brink
Oh, je vois, cela a du sens.
Chaussure
Existe-t-il un ventilateur automatique dans GL moderne comme GL_TRIANGLE_FAN du pipeline de fonctions fixes?
John P
5

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:

glVertexAttribPointer(..., n * sizeof(VERTEX_DATA), ...);

... 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.

MaKo
la source
2
"réglage de la foulée pour affecter le nombre de sommets dessinés pour le cercle" Super cool!
david van brink