2009-11-13 10 views
9

Anche se sembrano esserci pochi riferimenti aggiornati per OpenGL 3.x, l'attuale manipolazione di basso livello di OpenGL è relativamente semplice. Tuttavia sto avendo seri problemi nel tentativo di concettualizzare persino come si possa manipolare i VBO al fine di rendere un mondo dinamico.Come utilizzare i VBO OpenGL 3.x per rendere un mondo dinamico?

Ovviamente le modalità della modalità immediata del vecchio non sono applicabili, ma da dove vado? Scrivo una specie di struttura di scena e poi la converto in un insieme di vertici e la trasmetto in streaming al VBO, come potrei memorizzare i dati di traduzione? In tal caso, come sarebbe il codice saggio?

Fondamentalmente davvero incerto su come continuare.

risposta

9

Se tutto il vostro mondo è veramente dinamica, è possibile utilizzare il flag GL_STREAM_DRAW_ARB utilizzo e resettare i dati su ciascun frame. Non preoccuparti di manipolarlo, prova semplicemente a trasmettere il più efficiente possibile.

Tuttavia, presumo che si disponga di una scena costituita da più oggetti rigidi che si spostano l'uno rispetto all'altro. In questo caso, utilizzare un VBO per ciascun oggetto e specificare il flag di utilizzo GL_STATIC_DRAW_ARB. È quindi possibile impostare la trasformazione modelview per ogni istanza di un oggetto e renderizzarli mediante una chiamata di estrazione per istanza.

Una regola empirica (sul PC) è quella di emettere non più di una chiamata di richiamo per MHz della CPU. Questa è una stima approssimativa, ma c'è del vero. Non preoccuparti di mettere più oggetti indipendenti in un singolo VBO o altri trucchi di prestazioni se rimani al di sotto di questo limite.

+1

+1 per riconoscere il batching come il più grande problema con la codifica grafica in questi giorni. 1 richiamo per Mhz mi sembra ottimistico dopo qualche codifica di OpenGL ES per iPhone - Ho trovato che sono limitato a 30-40 lotti per mantenere un framerate decente! – tsalter

+0

Ok, avrei dovuto aggiungere che questa regola potrebbe non essere applicabile direttamente ai dispositivi mobili. L'ho visto per la prima volta su alcune diapositive GDC alcuni anni fa e mi è servito molto bene sui PC Windows. –

+0

Btw, ho appena trovato le diapositive qui: http://ati.amd.com/developer/gdc/D3DTutorial3_Pipeline_Performance.pdf (principalmente D3D9, OpenGL a pagina 28) –

5

L'utilizzo di VBO non significa che è necessario eseguire il rendering dell'intera scena con una sola chiamata di estrazione. È comunque possibile emettere più chiamate di disegno e impostare diverse matrici di trasformazione lungo il percorso.

Ad esempio, se si utilizza uno scenegraph, ciascun modello nello scenegraph può corrispondere a una singola chiamata di disegno. In tal caso, il modo più semplice per utilizzare i VBO è creare un VBO separato per ogni modello.

Come ottimizzazione, potresti essere in grado di combinare più modelli in un singolo VBO, quindi passare in offset diversi da zero quando effettui le chiamate di estrazione; questo preleva il modello corretto dal VBO. È anche auspicabile combinare più chiamate di disegno in una singola chiamata di disegno, ma ciò non è possibile se hanno bisogno di avere trasformazioni indipendenti. (In realtà è possibile in certe situazioni, se si utilizza l'istanza o la miscelazione di vertice, ma vi suggerisco di ottenere le basi fuori del modo prima.)

9

Risposta breve:

Usa glMapBufferRange e aggiornare solo il subrange che necessita di una modifica.

Risposta lunga:

Il trucco è quello di mappare il buffer già esistente con glMapBufferRange, e quindi mappare solo l'intervallo si ha bisogno. Alla luce di questi presupposti:

  • la geometria utilizza per-vertex animation morphing
  • Il conteggio dei vertici per i modelli è costante durante l'animazione.

quindi è possibile utilizzare glMapBufferRange per aggiornare solo le parti che cambiano, e lasciare il resto dei dati da soli. Caricamenti completi utilizzando glBufferData sono lenti come una tartaruga, perché eliminano il vecchio archivio di memoria e ne assegnano uno nuovo. Questo è oltre al caricamento dei nuovi dati. glMapBufferRange consente solo di leggere/scrivere dati esistenti, non ha alcuna allocazione o deallocazione.

Tuttavia, se si utilizza l'animazione dello scheletro, piuttosto passare le trasformazioni del vertice come matrici 4x4 per-vertice allo shader del vertice e fare i calcoli lì. I dati per vertice sono ovviamente specificati con glVertexAttribPointer.

Inoltre, si ricorda che è possibile leggere i dati di trama nel vertex shader e che OpenGL 3.1 ha introdotto alcune nuove chiamate di richiamo dell'istanza; glDrawArraysInstanced e glDrawElementsInstanced. Quelli combinati possono essere usati per ricerche specifiche dell'istanza. È possibile eseguire istanze per disegnare chiamate con gli stessi dati geometrici rilegati, ma inviare posizioni o qualsiasi dato per-vertice di cui avete bisogno come trame o array di texture. Questo può farti risparmiare dal mixare e abbinare diversi set di dati di array di vertici.

Immaginate se volete eseguire il rendering di 100 istanze dello stesso modello, ma con posizioni o combinazioni di colori differenti. O persino mappe di texture.