Chaque glDraw * est un appel de tirage.
1 glDrawArrays est 1 appel nul.
1 glDrawElements est 1 appel nul.
Peu importe (en ce qui concerne le nombre d'appels de tirage) combien de sommets ou d'index vous utilisez, 1 glDraw * est 1 appel de tirage.
Les cas simples de dessin de quads (en supposant que la version GL que vous utilisez n'a pas supprimé les quads) ou de triangles ne sont pas un bon exemple pour les comparer, car une liste de quads ou une liste de triangles peut être dessinée avec un seul appel à l'un ou l'autre, et glDrawArrays apparaîtra plus efficace car il n'a pas la surcharge supplémentaire d'indexation.
Prenons un cas un peu plus complexe, mais qui est représentatif d'un scénario plus réel. Imaginez que vous ayez un modèle composé de plusieurs bandes triangulaires et ventilateurs:
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
Dans cet exemple, l'utilisation de glDrawArrays vous donne un total de 6 appels de dessin pour le modèle. Cependant, les bandes et les ventilateurs peuvent facilement être convertis en triangles indexés, alors ajoutez des indices et cela devient:
glDrawElements (GL_TRIANGLES, .....);
C'est un appel nul, pour l'ensemble du modèle.
Les avantages de glDrawElements par rapport à glDrawArrays sont plus que la simple économie de mémoire, ce qui est la manière naïve de la mesurer. Il y a un potentiel d'économie de mémoire là où les sommets peuvent être réutilisés, car un index est généralement plus petit qu'un sommet (donc même si vous avez beaucoup d'indices en équilibre, ils seront plus petits), mais d'autres avantages incluent:
Nombre d'appels de tirage réduit. Chaque appel de tirage entraîne une surcharge de validation de l'état, de configuration, etc., et une grande partie de cette surcharge se produit du côté du processeur. En réduisant le nombre d'appels de tirage, nous évitons une grande partie de ces frais généraux.
Réutilisation des sommets. C'est bien plus qu'une simple économie de mémoire. Votre GPU a probablement un cache de vertex matériel, où les sommets récemment transformés peuvent être stockés; si le même sommet revient, et s'il est dans le cache, il peut être réutilisé depuis le cache plutôt que d'avoir à se transformer à nouveau. Votre matériel vérifiera le cache en comparant les indices, donc en termes OpenGL, la seule façon d'utiliser le cache est d'utiliser glDrawElements.
Donc pour répondre à vos questions spécifiques:
comment glDrawElements pourrait-il sauver les appels de tirage ...? Dans l'exemple que vous utilisez, ce n'est pas le cas. Chacun a un appel nul. Comme je l'ai expliqué ci-dessus, cet exemple est très mauvais pour comparer les deux.
comment l'utilisation de glDrawElements permettrait-elle d'économiser de l'espace ...? Parce que les indices sont plus petits que les sommets. Un index de 16 bits est de deux octets, un sommet position / couleur / texcoord est de 24 octets. 6 sommets est de 144 octets, 4 sommets plus 6 indices est de 108 octets.
Dans le cas de dessiner un carré à partir de 2 triangles ...? Un et un. Un appel glDraw * est un appel nul, le nombre de sommets ou d'indices utilisés n'est pas pertinent pour cette mesure. Mais je dois souligner à nouveau, c'est un très mauvais exemple pour comparer les deux.
Enfin, et pour compliquer un peu les choses, alors que glDrawElements avec des triangles est le chemin optimal sur les GPU de bureau, sur mobile, il peut être très différent. Certains GPU mobiles pourraient préférer glDrawArrays avec GL_TRIANGLE_STRIP (vous ajouteriez des triangles dégénérés pour concaténer des primitives dans ce cas), et je n'ai même pas abordé des sujets plus avancés tels que le redémarrage primitif ou le multi-dessin.