2010-07-10 22 views
5

Sono un po 'confuso sull'uso corretto di VBO in un programma OpenGL.Tecniche OpenGL VBO in C++

Voglio creare un algoritmo di paging del terreno, utilizzando una mappa chiamata da una heightmap in scala di grigi 4096x4096 come mappa "intera".

Da quello che ho letto, ogni vertice memorizzato nel VBO impiegherà 64 byte.

Il problema che ho è che la maggior parte delle fonti afferma che un singolo VBO dovrebbe avere dimensioni comprese tra 1 e 4mb e meno VBO è meglio. Tuttavia, secondo i miei calcoli, la memorizzazione di ciascun vertice richiederebbe un totale di circa un gigabyte di dati! (4096x4096x64) Questo non significa che ogni vertice potrebbe dover essere memorizzato più volte per ogni triangolo.

Né questo si adatta ai diversi veicoli e persone che sarebbero su questa mappa una volta ottenuta la parte del codice del terreno elaborata.

l'altra soluzione ho guardato era alla pagina i dati dal disco rigido mentre il programma è in esecuzione, ma un'altra fonte dice che è una cattiva idea di creare e distruggere durante l'esecuzione del programma, e che è anche buona norma avere il minor numero possibile di VBO.

Quello che voglio davvero sapere è, cosa mi manca? Sono sicuro che sto facendo una specie di supervisione enorme qui, perché una dimensione VBO massima di 4mb sembra solo estremamente bassa, anche se stavo caricando la trama in 64x64 blocchi e anche i diversi oggetti interattivi che avrebbero popolato la mappa .

O le mie aspettative su ciò che posso ottenere sono irrealistiche? C'è un metodo migliore a mia disposizione di cui non sono a conoscenza? Sto guardando i giochi come Oblivion o Fallout 3, e in qualche misura il Boundless Planet, e vedere enormi terreni, e mi chiedo come diavolo sia possibile.

Capisco come codificare, questo non è il mio primo approfondimento su OpenGL, ma è la mia prima volta che cerco di capire e utilizzare VBO.

Se qualcuno può far luce su dove la mia comprensione dei VBO sta andando male, sarebbe molto apprezzata.

risposta

9

Da quello che ho letto, ogni vertice memorizzato nel VBO impiegherà 64 byte.

Può richiedere il numero di byte desiderato, in base al formato del vertice.
posizione + normale + texcoords = 4 * (3 + 3 + 2) = 32 byte per vertice
posizione + normale + texcoords + vettore tangente (per bump) = 4 * (3 + 3 + 2 + 3) = 44 byte

Ciò non significa che ogni vertice potrebbe dover essere memorizzato più volte per ogni triangolo.

I vertici identici non devono essere memorizzati più volte. Usa i primitivi indicizzati (liste triangolari o strisce triangolari). Buffer di binding per gli indici, quindi utilizzare glDrawElements e glDrawRangeElements. Ricorda che puoi usare quad in OpenGL - non devi usare solo triangoli.

(4096x4096x64)

Non è necessario creare quad per ogni pixel sulla mappa. Alcune aree sono completamente piatte (cioè l'altezza non cambia), quindi aggiungendo triangoli extra ci sarà uno spreco di risorse. Se si aggiunge una sorta di algoritmo di semplificazione della mesh al panorama finito, si dovrebbe essere in grado di rilasciare un bel po 'di triangoli. Inoltre, troppi poligoni porteranno a problemi: un triangolo o un quadruplo dovrebbe richiedere diversi pixel.Se ci sono più primitive che dovrebbero occupare lo stesso pixel, il risultato renderizzato sarà un po '"rumoroso". Quindi dovrai tenere conto del livello di dettaglio desiderato.

Il problema che ho è che la maggior parte delle fonti afferma che un singolo VBO dovrebbe avere dimensioni comprese tra 1 e 4mb e meno VBO è meglio.

Non mi fiderei di tutte le fonti, soprattutto su Internet. Un sacco di persone che scrivono tutorial sono lontani dall'essere "esperti". Un'altra cosa è che in DirectX (non OpenGL), si consiglia di inserire tutto (cioè tutti gli oggetti con formato vertex compatibile) in un grande buffer statico di vertici (VBO analogico), quando possibile, ed evitare di commutare i buffer per ridurre il sovraccarico della CPU per il rendering delle chiamate. Quindi il consiglio che "VBO non dovrebbe essere più grande di 4 MB" mi sembra estremamente sospetto.

Le informazioni possono essere attendibili solo se proviene da uno sviluppatore API o da uno sviluppatore di driver (ATI o NVidia). O quando è assolutamente certo che l'autore (di tutorial o di articoli) abbia molta esperienza nel campo e non un altro sviluppatore di giochi di wannabe clueless. I documenti che provengono da GDC, Siggraph, ATI, NVidia possono essere considerati affidabili. Alcuni tutorial scritti da anonymouse "qualcuno" dovrebbero essere verificati per essere effettivamente corretti.

In ogni caso, per quanto riguarda le prestazioni, Microsoft aveva due documenti: "Top Issues for Windows Titles" "Performance Optimizations (Direct3D 9)" (DirectX roba, ma alcuni consigli può essere applicabile a OpenGL).

Inoltre, NVidia ha una raccolta di OpenGL resources, che include utilità relative alle prestazioni (GLexpert potrebbe essere utile per voi, e vi è NVIdia OpenGL SDK, ecc.). In generale, quando si tenta di migliorare le prestazioni, provare tecniche diverse e i risultati misurano anziché seguire ciecamente il consiglio di qualcuno. Guarda quanti fotogrammi in più al secondo ottieni usando una tecnica o un'altra.

Tuttavia, secondo i miei calcoli, la memorizzazione di ciascun vertice richiederebbe un totale di circa un gigabyte di dati! (4096x4096x64)

Questo è corretto se si costruisce l'intera mappa in questo modo. Ma non c'è motivo di caricare l'intera mappa in una volta, quindi avrai solo bisogno di un pezzo di mappa immediatamente visibile.

Sto guardando giochi come Oblivion o Fallout 3, e in qualche misura Boundless Planet, e vedere terreni enormi, e mi chiedo come diavolo sia possibile.

NON caricano tutto in una volta. Solo gli oggetti visibili, il "pezzo" corrente del terreno e la versione basso poligonale di pochi pezzi di terreno nelle vicinanze vengono caricati in qualsiasi momento. Il gioco memorizza solo oggetti che sono attualmente in uso o che saranno utilizzati a breve. Ottiene costantemente dati dall'HDD.

+0

Bene, grazie :) Lo terrò a mente quando guarderò tra gli esempi, forse la regola 4mb era appena superata, e grazie per il link alle risorse, GLexpert sarebbe diventato davvero utile quando si sperimentava questo! – Brian

+0

La raccomandazione 4mb è probabilmente la dimensione vbo ottimale per il rendering come definito per alcune schede nvidia. Questa dimensione ottimale è diversa per ogni carta, quindi la regola generale è di non usare vbo troppo piccoli o troppo grandi. – 5ound

1

La dimensione del vertice determina quanto spazio occuperà nel buffer dei vertici. Se il vertice consiste solo di una posizione 3D, avrete 12 byte per vertice.

Ciò non significa che ogni vertice potrebbe dover essere memorizzato più volte per ogni triangolo.

È possibile indicizzare i dati utilizzando un buffer di indice per rimuovere la necessità di vertici duplicati.

l'altra soluzione che ho visto era quella di pagina i dati dal disco rigido mentre il programma è in esecuzione, ma un'altra fonte dice che è una cattiva idea di creare e distruggere mentre il programma è in esecuzione, e che è anche la migliore pratica avere il minor numero possibile di VBO.

Sì, la creazione e la distruzione avranno un impatto negativo sulle prestazioni ma non vicino all'impatto di avere un enorme buffer di vertici. Se vuoi avere un terreno enorme; caricamento/rilascio di piccole parti di dati del terreno durante è la strada da percorrere.

Sono sicuro che sto facendo una sorta di enorme svista qui, perché una dimensione massima di 4 MB VBO sembra proprio estremamente basso, anche se ero il caricamento della texture in 64x64 blocchi, ed i diversi oggetti interattivi che popolerebbe anche la mappa.

Se si utilizza un vertice con 64 byte; 4 MB ti compra 65536 vertici. (256x256) Quale dovrebbe essere sufficiente per qualsiasi cosa, e se hai bisogno di più vertici li dividi tra diversi buffer di vertici.

Disclaimer: Personalmente ho solo recentemente iniziato a utilizzare OpenGL e non sarà di grande aiuto per rispondere a domande specifiche OpenGL.

+0

grazie per la risposta! Quindi, nella mia situazione, creare e rilasciare sarebbe una linea di condotta positiva? La ragione per cui ho menzionato 64 byte è che la maggior parte delle risorse online utilizza una struttura dati molto simile per un vertice. I commenti sembrano formattarsi male con frammenti di codice, ma la struttura particolare può essere trovata nel primo blocco di codice a: http://sdickinson.com/wordpress/?p=122 A causa dell'approvazione universale di questa struttura Avevo l'impressione che i VBO richiedessero i dati dei vertici in questo formato. – Brian

+0

Brian: "approvazione universale di questa struttura"? se stai parlando dei commenti nel blog, non vedo nessuno parlare del formato dei vertici. Non esiste un formato vertice fisso, VBO è solo un pezzo di memoria (VRAM) interpretato come luogo in cui i vertici vengono memorizzati senza un particolare formato di vertice, è specificato dal client. –

+0

scusate per l'errore: p Quello che voglio dire è che ero sotto il presupposto che era il modo "giusto" di fare le cose come altre fonti utilizzavano anche il riempimento per rendere 64 byte i dati per quello che affermano essere prestazioni ottimali. Non sto discutendo con te in alcun modo, infatti ho preso nota delle informazioni qui. Sto semplicemente fornendo le mie ragioni sul perché inizialmente ho detto 64 byte. – Brian

1

Come già accennato, la dimensione di un vertice in un VBO dipende dal formato del vertice, quindi non esiste un formato fisso e quindi la dimensione non è fissa. Le statistiche sulle dimensioni VBO ottimali tendono ad essere obsolete, non aspettarti di fare bene la prima volta, basta giocare con le dimensioni e il profilo, non ti ci vorrà molto tempo.

Circa il numero di VBO che è possibile avere, sì a molti VBO significa molte chiamate di estrazione. Inoltre nessuno ha detto che li hai distrutti completamente, puoi riutilizzarli tutte le volte che vuoi.

Quello che stavi pensando di avere una sorta di algoritmo di paging non è affatto male, c'è un algoritmo di rendering del terreno ben noto che utilizza questo approccio chiamato Chunked LOD. Questo algoritmo utilizza un thread di paginazione separato per il rendering fuori dal core del terreno statico.

Non cercare di trovare l'ultima soluzione perfetta, impara ad accettare l'imperfezione. Non dipendere da tutti per darti la risposta o tutti i dettagli, fallo da solo e vedi. Puoi sempre refactoring e/o ottimizzare in seguito quando diventa effettivamente un problema altrimenti non finirai mai.

1

Sospetto che non stiate utilizzando le mappe di altezza come previsto. Si dispone di un'immagine 4096x4096, che è una matrice di pixel, non destinata a essere utilizzata come vertici. L'intero punto di memorizzazione delle altezze in una trama (ad esempio una mappa di altezza) è di evitare un tale livello di dettaglio nella geometria (cioè nei buffer dei vertici).

L'esatta tecnica di utilizzo dipende dal contesto.Se il terreno è solo per visualizzazione, ti consigliamo di presentarlo su un quad (4 vertici) e di utilizzare shader come light maps, displacement mapping o parallax mapping. Se è inteso per alcune interazioni con altri oggetti (ad es. I personaggi che vi camminano sopra), allora è necessaria una certa geometria, ma certamente non 4096x4096. Here's one way per campionare la mappa di altezza in modo adattivo, in base al livello di dettaglio locale.

0

Se i dati della pagina sono inseriti/disinseriti, sono necessari almeno 4 VBO nel caso in cui si esegua il rendering vicino a un limite di "quattro angoli". Ma mentre ti muovi, puoi sostituire i dati all'interno di questi quattro VBO invece di crearli/rilasciarli tutto il tempo. Per questo metodo dovresti usare uno dei flag di utilizzo "dinamici", per far sapere a OpenGL che i dati potrebbero cambiare, ma saranno usati più volte ogni volta.

0

Non sono sicuro di alcune di queste cose, ma da quello che ho capito è possibile avere vbo di qualsiasi dimensione utilizzando 1 vbo per trama, anche se i dati del modello e della trama si estendono su più elementi di più oggetti. Potrebbe essere confuso comunque.

http://www.swiftless.com/tutorials/opengl/6_vbo.html