Domanda

Sto cercando di avere un'idea chiara di quando dovrei usare array indicizzati di vertici OpenGL, disegnate con gl [Multi] DrawElements e simili, rispetto a quando dovrei semplicemente utilizzare array contigui di vertici, disegnate con gl [ ] Multi DrawArrays.

( Aggiornamento:. Il consenso nelle risposte che ho ricevuto è che si dovrebbe sempre fare uso di vertici indicizzati)

Ho di nuovo andata e indietro su questo tema più volte, così ho intenzione di delineare la mia comprensione attuale, nella speranza che qualcuno può o dirmi che sono ora finalmente più o meno corrette, o il punto in cui il mio altro fuori rimanenti incomprensioni sono. In particolare, ho tre conclusioni, in grassetto. Si prega di correggerli se sono sbagliate.

Un caso semplice è se la mia geometria consiste di maglie per formare superfici curve. In questo caso, i vertici nel mezzo della maglia avranno attributi identici (posizione, normale, colore, struttura coord, ecc) per ogni triangolo che utilizza il vertice.

Questo mi porta a concludere che:

1. Per la geometria con poche cuciture, array indicizzati sono una grande vittoria.

Segui regola 1 sempre, ad eccezione di:

Per geometria che è molto 'blocchi', in cui ogni bordo rappresenta una cucitura, il beneficio di array indicizzati è meno evidente. Di prendere un semplice cubo come esempio, anche se ogni vertice viene utilizzato in tre diverse facce, non possiamo condividere vertici tra loro, perché per un singolo vertice, normali alla superficie (ed eventuali altre cose, come il colore e la consistenza co-ord ) differirà su ciascuna faccia. Di qui la necessità di introdurre esplicitamente posizioni dei vertici ridondanti nella nostra matrice, in modo che la stessa posizione può essere utilizzato più volte con diversi normali, ecc Questo significa che gli array indicizzati sono meno dell'uso.

es. Quando il rendering di una sola faccia di un cubo:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

(questo può essere considerato in modo isolato, in quanto le giunture tra il viso e tutte le facce adiacenti significa che nessuno di questi vertici possono essere condivisi tra le facce)

se il rendering utilizzando GL_TRIANGLE_FAN (o _STRIP), allora ogni faccia del cubo può essere reso in tal modo:

verts  = [v0, v1, v2, v3]
colors = [c0, c0, c0, c0]
normal = [n0, n0, n0, n0]

Aggiunta di indici non consente di semplificare questo.

Da questo concludo che:

2. Durante il rendering della geometria che è tutte le cuciture o per lo più cuciture, quando si utilizza GL_TRIANGLE_STRIP o _FAN, allora non avrei mai usare array indicizzati, e dovrebbe invece utilizzare sempre gl [Multi] DrawArrays.

( Aggiornamento:. risposte indicano che questa conclusione è sbagliata Anche se gli indici non ci permettono di ridurre le dimensioni degli array qui, dovrebbero comunque essere utilizzati a causa di altri vantaggi di prestazioni, come discusso nei commenti)

L'unica eccezione alla regola 2 è:

Quando si utilizza GL_TRIANGLES (invece di strisce o ventilatori), allora metà dei vertici può ancora essere riutilizzati per due volte, con normali e colori identici, ecc, perché ogni faccia del cubo è reso come due triangoli separati. Anche in questo caso, per la stessa faccia singolo cubo:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

Senza indici, utilizzando GL_TRIANGLES, gli array sarebbe qualcosa di simile:

verts =   [v0, v1, v2,  v2, v3, v0]
normals = [n0, n0, n0,  n0, n0, n0]
colors =  [c0, c0, c0,  c0, c0, c0]

Poiché un vertice e un normale sono spesso 3 galleggia ciascuno, e un colore è spesso 3 byte, che dà, per ogni faccia del cubo, di:

verts   = 6 * 3 floats = 18 floats
normals = 6 * 3 floats = 18 floats
colors  = 6 * 3 bytes  = 18 bytes

= 36 floats and 18 bytes per cube face.

(capisco il numero di byte potrebbe cambiare se si utilizzano diversi tipi, le cifre esatte sono solo per l'illustrazione).

Con indici, possiamo semplificare questo un po ', dando:

verts   = [v0, v1, v2, v3]     (4 * 3 = 12 floats)
normals = [n0, n0, n0, n0]     (4 * 3 = 12 floats)
colors  = [c0, c0, c0, c0]     (4 * 3 = 12 bytes)
indices = [0, 1, 2,  2, 3, 0]  (6 shorts)

= 24 floats + 12 bytes, and maybe 6 shorts, per cube face.

Vedere come in quest'ultimo caso, vertici 0 e 2 sono utilizzati due volte, ma solo rappresentata una volta in ciascuna delle verts, normali e array colori. Sembra una piccola vittoria per mezzo di indici, anche nel caso estremo di ogni singolo bordo geometria essendo una cucitura.

Questo mi porta a concludere che:

3. Quando si utilizza GL_TRIANGLES, si dovrebbe sempre usare array indicizzati, anche per la geometria che è tutte le cuciture.

Si prega di correggere il mio conclusions in grassetto se si sbagliano.

È stato utile?

Soluzione

Da questo concludo che quando il rendering della geometria che è tutte le cuciture o per lo più cuciture, quando si utilizza GL_TRIANGLE_STRIP o _FAN, allora non avrei mai usare array indicizzati, e dovrebbe invece utilizzare sempre gl [Multi] DrawArrays.

No, e il motivo è abbastanza semplice.

Il tuo conclusione si basa sul fatto che avete analizzato un singolo quad composta da due triangoli. Questi due triangoli disegnati utilizzando ventilatore triangolo / striscia non possono essere semplificati utilizzando matrici indicizzati.

Ma provate a pensare a una grande geometria terreno. Ogni blocco terreno è disegnato come un quad, utilizzando ventilatore triangolo / striscia primitiva. Ad esempio:

Ogni striscia triangolo in figura ha in comune tutti i vertici del triangolo con strisce adiacenti, e utilizzando gli indici permette di comprimere la definizione della geometria, invece di ripetere vertici per ciascuna striscia triangolo.


Fondamentalmente, primitive disegno (triangoli, ventilatori e nastri) utilizzando indici sono utili quando è possibile condividere la maggior parte dei vertici di un singolo primitiva con un altro.

La condivisione delle informazioni consente di risparmiare larghezza di banda di trasmissione dati, ma non è l'unico vantaggio. Effettivamente array indicizzati consentono:

  • Evitare la sincronizzazione delle informazioni appartenente allo stesso vertice "concettuale", specificato molte volte
  • Permette di eseguire la stessa operazione shader su un singolo vertice invece eseguire molte volte, una per ogni vertice duplicazione.
  • Inoltre, combinando l'uso di strisce triangolo / ventilatori e indici consente all'applicazione di comprimere indici tampone in quanto la specifica striscia / ventilatore richiede meno indici (un triangolo richiede sempre 3 indici per ogni faccia).

array indicizzato non può essere utilizzato, come è stato specificato, ogni volta che un vertice non può condividere ogni informazione ad esso associate (colore, coordinate consistenza e così via) con un altro vertice coincidenti.


Solo per ragioni di completezza, la dimensione delle informazioni necessarie per la specifica geometria non è l'unico fattore wich determinare l'operazione resa ottimale.

Infatti, un altro fattore fondamentale per il rendering primitiva è la localizzazione della cache dei dati. dati geometrici mal specificati (oggetti buffer non interfogliati, strisce di triangoli lunghi ...) provoca un sacco di cache miss, degradanti caratteristiche della scheda grafica.

Al fine di ottimizzare il funzionamento di rendering, la specifica vertice deve essere riordinati in un modo per riutilizzare i vertici specificati in precedenza, con il più probabilità. In tal modo, la linea di cache grafico carta può riutilizzare vertici specificati in precedenza senza recupero dalla memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top