Ogni glDraw * è un richiamo.
1 glDrawArrays è 1 call draw.
1 glDrawElements è 1 call draw.
Non importa (per quanto riguarda il conteggio delle chiamate di disegno) quanti vertici o indici usi, 1 glDraw * è 1 chiamata di disegno.
I semplici casi di disegno di quad (supponendo che la versione GL che usi non abbia rimosso quad) o triangoli non sono un buon esempio per confrontarli, perché un elenco di quad o un elenco di triangoli può essere disegnato con una sola chiamata a uno, e glDrawArrays appariranno più efficienti perché non hanno l'overhead aggiuntivo dell'indicizzazione.
Prendiamo un caso leggermente più complesso, ma che è rappresentativo di uno scenario più reale. Immagina di avere un modello composto da più strisce triangolari e ventole:
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
glDrawArrays (GL_TRIANGLE_STRIP, .....);
glDrawArrays (GL_TRIANGLE_FAN, .....);
In questo esempio, l'utilizzo di glDrawArrays fornisce un totale di 6 chiamate di disegno per il modello. Tuttavia, sia le strisce che i fan possono essere facilmente convertiti in triangoli indicizzati, quindi aggiungi indici e diventa:
glDrawElements (GL_TRIANGLES, .....);
Questa è una chiamata di pareggio, per l'intero modello.
I vantaggi di glDrawElements rispetto a glDrawArrays non sono solo il risparmio di memoria, che è il modo ingenuo di misurarlo. Esiste il potenziale per il salvataggio della memoria in cui i vertici possono essere riutilizzati, poiché un indice è in genere più piccolo di un vertice (quindi anche se si hanno molti indici in bilico saranno più piccoli), ma altri vantaggi includono:
Conteggio chiamate di prelievo ridotto. Ogni chiamata di disegno comporta un certo sovraccarico dallo stato di convalida, impostazione delle cose, ecc. E gran parte di questo sovraccarico si verifica sul lato CPU. Riducendo il numero di call draw evitiamo gran parte di questo sovraccarico.
Riutilizzo del vertice. Questo è molto più di un semplice risparmio di memoria. La tua GPU probabilmente ha una cache dei vertici hardware, dove possono essere memorizzati vertici trasformati di recente; se lo stesso vertice si ripresenta e se si trova nella cache, può essere riutilizzato dalla cache anziché dover trasformarlo di nuovo. Il tuo hardware controllerà la cache confrontando gli indici, quindi in termini OpenGL l'unico modo per usare la cache è usare glDrawElements.
Quindi, per rispondere alle tue domande specifiche:
come potrebbe glDrawElements salvare le chiamate di disegno ...? Nell'esempio che usi, non lo fa. Ognuno ha un call call. Come discuterò sopra, questo esempio è pessimo per confrontare i due.
in che modo l'utilizzo di glDrawElements consente di risparmiare spazio ...? Perché gli indici sono più piccoli dei vertici. Un indice a 16 bit è di due byte, un vertice position / color / texcoord è di 24 byte. 6 vertici è 144 byte, 4 vertici più 6 indici è 108 byte.
Nel caso di disegnare un quadrato da 2 triangoli ...? Uno e uno. Una chiamata glDraw * è una chiamata di disegno, il numero di vertici o indici utilizzati è irrilevante per questa misurazione. Ma devo ribadire, questo è un pessimo esempio per confrontare i due.
Infine, e solo per complicare un po 'le cose, mentre glDrawElements con i triangoli è il percorso ottimale sulle GPU desktop, sui dispositivi mobili potrebbe essere molto diverso. Alcune GPU mobili potrebbero preferire glDrawArrays con GL_TRIANGLE_STRIP (in questo caso aggiungeresti triangoli degeneri per concatenare le primitive), e non ho nemmeno toccato argomenti più avanzati come il riavvio primitivo o il disegno multiplo.