Le moyen le plus rapide de dessiner des quads dans OpenGL ES?

22

J'utilise OpenGL ES 2.0, j'ai un tas de quads à dessiner, j'aimerais pouvoir passer seulement 4 sommets par quad comme si j'utilisais GL_QUADS, mais en gros, je veux juste savoir la meilleure façon de dessiner un tas de quads séparés.

Jusqu'à présent, ce que j'ai trouvé, je pouvais le faire: -GL_TRIANGLES (6 sommets par quad) -Générer GL_TRIANGLE_STRIP (6 sommets par quad)

Possibilités que j'ai trouvées: -GL_TRIANGLE_STRIPS avec une valeur d'index spéciale qui réinitialise la bande quad (cela signifierait 5 index par quad, mais je ne pense pas que ce soit possible est OpenGL ES 2.0)

Jonathan
la source

Réponses:

33

Utilisez simplement le tampon d'index et GL_TRIANGLES. Dans ce cas, vous avez besoin de 4 sommets + 6 indices par quadruple (6 indices supplémentaires peuvent sembler trop lourds mais en réalité ce n'est pas le cas - une fois que vous avez construit votre tampon d'index, vous n'avez pas besoin de le toucher à nouveau). Voir cette page pour plus d'informations (recherche de glDrawElements)

Exemple de code simple:

GLfloat vertices[] = {-1, -1, 0, // bottom left corner
                      -1,  1, 0, // top left corner
                       1,  1, 0, // top right corner
                       1, -1, 0}; // bottom right corner

GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                     0,2,3}; // second triangle (bottom left - top right - bottom right)

glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);

De plus, si vous dessinez un seul quadruple, vous n'avez besoin que de 4 sommets pour le dessiner avec des bandes triangulaires ( comme indiqué dans wikipedia ), mais je suppose que vous le saviez déjà.

user4241
la source
L'astuce traditionnelle pour fusionner plusieurs bandes de triangle en une seule bande est la "triangles dégénérés": la répétition du dernier élément d'une bande et du premier élément de la bande suivante crée 2 triangles avec une zone nulle, qui ne dessinent donc rien. Prenons le deuxième indice quadruple (4, 5, 6, 7). Le tampon d'index pour GL_TRIANGLE_STRIP de deux quads pourrait être: {0, 1, 2, 3, 3, 4,4, 5, 6, 7}. Les triangles dégénérés sont 3,3,4et 3,4,4. Est-ce que ça vaut le coup? Non, sauf si vos quads ont tendance à venir par paires (ou plus) avec des bords communs. Si le 2e quad est {3, 2, 4, 5}, alors la bande l'est {0,1,3,2,5,4}.
ToolmakerSteve
8
Et pour que cela soit clair pour quiconque vient et doit dessiner un tas de quads: pour des raisons de performances, NE copiez PAS le code ci-dessus et faites un appel à glDrawElements ONCE FOR EACH QUAD . Au lieu de cela, créez UN tableau de sommets et UN tableau d'index qui inclut TOUS les quads que vous souhaitez dessiner. En utilisant GL_TRIANGLES, deux quads pourraient avoir des indices {0,1,2, 0,2,3, 4,5,6, 4,6,7}ou tout aussi bons {0,1,2, 2,3,0, 4,5,6, 6,7,4}. Bonne classe pour aider c'est glText Android / SpriteBatch
ToolmakerSteve
6

L'utilisation de tampons d'index n'est pas nécessairement plus rapide, comme indiqué dans les documents Apple, "Pour de meilleures performances, vos modèles doivent être soumis comme une seule bande triangulaire non indexée à l'aide de glDrawArrays" .

Donc, même si a le GL_TRIANGLE_STRIPfera dans 4 sommets sans avoir besoin d'un tampon d'index, et vous pouvez utiliser un tampon d'index, il est assez boiteux d'essayer de "sauvegarder" en répétant 2 sommets . Pour cette raison, je vous suggère de dessiner 2 séparations GL_TRIANGLESet de répéter les 2 sommets sur la diagonale .

bobobobo
la source
8
Um non. Ce que dit ce document, c'est que vos modèles soient soumis comme une seule bande triangulaire INDEXÉE. Et la phrase suivante est: "Pour éviter de spécifier plusieurs fois les données pour le même sommet dans le tampon de sommet, utilisez un tampon d'index distinct et dessinez la bande triangulaire à l'aide de la fonction glDrawElements". C'est exactement ce que vous avez décidé «boiteux».
davidf2281
3
Étant donné que le paragraphe doc fait désormais référence à glDrawElements plutôt qu'à glDrawArrays, il a probablement été réécrit depuis cette réponse. Néanmoins, le point soulevé par le doc était que, pour les performances, fournir une seule bande (plutôt que plusieurs bandes, donc plusieurs appels gl). Dans cette situation, je pense que la différence entre l'utilisation ou non d'indices est insignifiante ; ce qui importe, c'est de tout mettre dans un seul tableau de sommets (plus un tableau d'index facultatif), afin que vous puissiez faire un seul appel gl.
ToolmakerSteve
0

Le gros gain sur le bureau est de déplacer les données dans les VBO GL_STATIC_DRAW. Vraisemblablement, cela est également vrai sur le GPU MBX de l'iPhone.

Volonté
la source
-2

L'utilisation GL_TRIANGLE_FANpour un quad utilise 4 sommets, pas 6.

Mr. Blah
la source
Oui, mais c'est le cas GL_TRIANGLE_STRIP, comme d'autres réponses l'ont déjà souligné.
Anko
@Monsieur. Blah - Vous avez manqué le point de la question, qui est de savoir comment faire efficacement un tas de quads. Il ne faut pas faire un appel gl pour chaque quad, mais plutôt combiner beaucoup de quads en un seul tableau, qui peut être dessiné avec un seul appel gl. GL_TRIANGLE_FAN n'aidera pas à cela, donc est rarement utile dans le rendu haute performance.
ToolmakerSteve