Ampio buffer di vertici rispetto a più chiamate di disegno


14

Ho appena iniziato con OpenGL e sto tentando di usarlo per creare un gioco 2D. In questo gioco, ho una griglia esagonale composta da una grande varietà di esagoni di colore diverso. Come programmatore OpenGL principiante, vedo due modi per disegnare questa griglia:

  1. Utilizzo di un buffer di vertici con i dati per un singolo esagono, quindi utilizzo di un valore di offset uniforme e iterazione sulla CPU per disegnare lo stesso programma molte volte fino a quando non ho una griglia.
  2. Creazione di un buffer vertice pre-calcolato singolare molto grande che disegna tutti gli esagoni in una singola chiamata.

Qual è il metodo più efficiente? C'è un modo migliore per farlo?


Il tuo buffer di vertici pre-calcolato deve solo estendersi oltre lo schermo di un esagono, puoi quindi falsificarlo scorrendo uniformemente fino a quando non vai a un esagono completo e poi "deformando" indietro, poiché per i colori in quello scenario, puoi mantenere un Trama 2D sulla GPU, leggila nello shader di vertice e interpola piatta nello shader di frammenti.
MickLH,

I passaggi di solito si riferiscono a una situazione in cui un'operazione di rendering si basa sui risultati di un'operazione precedente. Quello che stai chiedendo in questa domanda è in realtà correlato alla riduzione del numero di chiamate di estrazione in un singolo passaggio. So che sembra pedante, ma è molto importante capire la differenza, altrimenti gli algoritmi multi-pass non avranno molto senso;)
Andon M. Coleman,

@ AndonM.Coleman Hmm, grazie, chiaramente non ho familiarità con la terminologia grafica. Quindi, in questo caso, come lo descriverei? Chiamate multiple di shader / programmi?
Alexis King,

Puoi immediatamente dire che si tratta di un algoritmo a passaggio singolo perché non esiste alcuna dipendenza dell'ordine; puoi disegnare questi esagoni in qualsiasi ordine e ottenere comunque lo stesso risultato. Potresti ricevere più chiamate di disegno per fornire a OpenGL i dati richiesti per renderli, ma OpenGL è effettivamente libero di disegnarli tutti in parallelo poiché non vi sono dipendenze. Se fosse multi-passaggio , l'esagono B potrebbe richiedere il risultato dell'esagono A prima che possa essere disegnato, oppure potrebbe essere necessario disegnare lo stesso esagono più volte e combinare il risultato.
Andon M. Coleman,

Risposte:


9

Esistono davvero alcuni modi per creare una griglia del genere.

Il modo più efficiente sarebbe istanziare. In questo modo crei il tuo esagono solo una volta in un VBO e lo visualizzi cento, mille o un milione di volte. Puoi farlo manualmente usando shader con uniformi come hai detto al punto 1, ma c'è anche una funzionalità OpenGL integrata per questo. Per questo, dai un'occhiata a glDrawElementsInstanced .

Si noti che l'istanziamento è solo più veloce di altri metodi se si disegna più di una certa quantità di oggetti istanziati. Ad esempio, il disegno 300 può essere più veloce utilizzando 1 VBO di grandi dimensioni, ma il disegno di 2 milioni può essere più veloce se si utilizza il rendering con istanza.

Se si utilizza il rendering con istanza, è possibile inviare i dati per oggetto utilizzando Divisori di attributi . Nel tuo caso vorresti inviare la posizione e il colore.

Un buon tutorial sul rendering istanziato: fare clic

Il modo migliore è provare entrambi i metodi e verificare la quantità di millisecondi necessari per disegnare 1 fotogramma. In questo modo impari anche in entrambi i modi, il che è sempre positivo.

Si noti inoltre che il rendering con istanza è una funzionalità OpenGL moderna e che sarà necessario utilizzare shader per utilizzarlo. Ma è sempre meglio impararlo nel modo corretto dall'inizio.


2
L'istanza non è necessariamente la più efficiente; in molte implementazioni di cui ho visto i profili, il supporto istante è stato attaccato per la conformità ma più lentamente rispetto al disegno individuale di molti oggetti (in effetti, era probabilmente solo un loop mal implementato nel driver che faceva proprio quella cosa). È un'opzione e buona, ma bisogna fare attenzione a profilare e testare su SO / hardware target prima di fare qualsiasi ipotesi sul "più efficiente".
Sean Middleditch,

Concordato. Ho visto diverse prestazioni su Windows / Linux e Ati / nVidia per esempio. Grazie per l'aggiunta.
Basaa,

1
Infatti. Se si disegnano più mesh combinate all'interno di un singolo vbo (che condividono lo stesso spazio). L'istanza non potrebbe essere più veloce. Il problema con l'istanziamento è: i vertici non sono istanze incrociate calcolate in parallelo. Elimina solo gpu / cpu / gpu sync / drawcall. Quindi è più veloce disegnare un buffer di vertici contenente 1000 sfere che disegnare 1000 sfere con istanziamenti hardware. (nessuna riduzione della frustum / ottimizzazione dei dettagli della distanza dell'oggetto coinvolta)
Jeroen van Langen

3

Il metodo 1 è più semplice da codificare e andrà bene finché non avrai troppi esagoni in vista contemporaneamente. Potresti voler rimanere fedele a questo dato che sei nuovo in OpenGL, per evitare di mettere troppa complessità sul tuo piatto in una volta.

Se ci sono un gran numero di esagoni (come diverse centinaia o più di un migliaio) in vista contemporaneamente, sarebbe necessario un metodo overhead per evitare che il sovraccarico della CPU esegua così tanti singoli disegni. Il metodo 2 funzionerebbe per questo, o ancora meglio, usando instancing. Mi aspetto che l'istanziamento sia più veloce del metodo 2, o sicuramente non peggio, dal momento che devi solo aggiornare un buffer di dati per istanza anziché un buffer (molto più grande) di dati vertici per tutte le istanze.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.