Unione di geometria / mesh senza perdere vantaggi


11

In three.js possiamo semplicemente unire la geometria per limitare la quantità di chiamate di disegno e quindi aumentare le prestazioni. In un semplice test con un materiale, ho potuto disegnare 50.000 cubi + ombre a 60 fps sulla mia GPU GTX660. Senza la fusione della geometria, 5.000 cubi hanno già causato un problema.

Mi chiedo come preservare i vantaggi del rendering di ogni mesh di cubo da sola. Ad esempio, come scegliere una mesh cubica quando tutto viene unito in una geometria? Per impostazione predefinita, questo non è ovviamente possibile.

Esiste una tecnica comune per questo problema? Dopo tutto, ho tutti gli oggetti mesh non uniti anche dopo la fusione. Quindi ci deve essere un modo per utilizzarli per la raccolta?

Cosa voglio fare in breve

  • SimCity come gioco a scopo di apprendimento
  • Ogni casa è una maglia cubica
  • Vuoi rendere 50.000 case ed essere in grado di aggiungere e rimuovere case
  • La selezione della casa tramite il cursore del mouse (selezione) deve essere possibile

Non sono sicuro che ti sia utile, ma lo menziono per completezza. Simplygon ha un modello tariffario basato su royalty per gli sviluppatori indipendenti e può fare molto di questa mesh unendo e partizionando in fase di progettazione.
steeveeet

Risposte:


11

Ok ho capito. Dopo aver unito l'intera geometria insieme, ho ancora le singole mesh in un array. Quindi posso semplicemente usare queste maglie per il raycasting, anche se non sono nemmeno renderizzate. Mi ci è voluto un po 'per rendermene conto.

inserisci qui la descrizione dell'immagine

Per il prelievo utilizzo questa implementazione octree: http://threejs.org/examples/#webgl_octree_raycasting

Ciò riduce i test di intersezione per aggiornamento da 50.000 a ~ 500. Senza l'ottavo i fps diminuiranno fortemente.

Lo scafo di raccolta arancione che vedi è in realtà la mesh ora renderizzata (+1 call draw) con un materiale modificato e dimensioni modificate.

inserisci qui la descrizione dell'immagine

Quindi immagino che il prossimo passo sia implementare una sorta di partizionamento delle mappe. Cioè, suddividere la geometria unita in più pezzi. La ragione di ciò è che la geometria unita ha una grande quantità di vertici. Ciò significa che se sposto la mappa al 99% fuori dallo schermo, la scheda grafica deve ancora elaborare tutti i vertici perché la geometria è ancora in vista, almeno l'1% di essa. Quindi, se è rotto, devono essere resi solo i pezzi in vista.


Grazie mille per questa intuizione. Ho cercato anche di trovare un modo per farlo, e penso che la tua soluzione qui sia la più eccellente! Domanda veloce però: per il tuo elenco locale di oggetti (ad es. Three.Object3D's), che tipo di proprietà sono richieste per il funzionamento di rayCaster.intersectObjects ()?
AlvinfromDiaspar,

Molto ben fatto.
ClassicThunder,

Ho un problema simile, ma in qualche modo non riesco a far funzionare il raycasting con r70. Hai fatto qualcosa di speciale durante la creazione e l'unione delle scatole? Uso il seguente codice ( pastebin.com/PStaAF3P ) per creare e unire i nodi, ma forse manca qualcosa per far funzionare il raycaster?
fhahn,

Domanda veloce: sto facendo qualcosa di molto simile a te (una mappa 3d basata su dati geoJSON). Con il tuo metodo, ogni volta che ruoti la telecamera devi ruotare anche le mesh di edifici preesistenti? O aggiungi semplicemente le singole caselle alla scena ma non le visualizzi?
Spencer,

@Spencer Non è necessario ruotare. Tengo le singole caselle nella matrice globale e aggiungo solo geometria unita alla scena. È quindi possibile eseguire il raycasting con l'oggetto nell'array globale, poiché raycaster dipende dalla matrice della telecamera e dalla posizione di ciascuna casella. Molto probabilmente non è il modo migliore, questa è stata solo una prova del concetto per me. Non eseguo più tre file a questo punto.
user990827

1

Per il prelievo potresti anche renderizzare gli ID per ciascun cubo su un altro target di rendering e controllare quale sia il valore ID sul cursore. Il vantaggio è che il picking è pixel perfetto e funziona in modo efficiente anche per geometrie più complesse.

Se tutti gli oggetti hanno la stessa geometria, è possibile utilizzare il rendering con istanza. Un flusso definisce la geometria, mentre un altro definisce le proprietà per istanza (ad es. Trasformazione). Per l'abbattimento dei frustum è necessario creare il flusso di istanza di ciascun frame in base al test di visibilità. Se si dispone di una grande quantità di oggetti, è possibile che si desideri posizionare tali oggetti in un ottetto libero o qualcosa per accelerare l'abbattimento.


0

Non sono sicuro dei particolari di three.js, ma in generale OpenGL mi vengono in mente due possibili maiali delle prestazioni:

  1. Hai preso in considerazione l'istanza? Avrai solo bisogno di un call call e di usare meno VRAM.
  2. Hai dato un'occhiata seria all'algoritmo di raccolta? Se i tuoi cubi hanno volumi di delimitazione in un elenco anziché in un albero, ad esempio, ciò spiegherebbe una differenza di tale entità.

0

Un altro approccio che puoi adottare è costruire un attributo vertice nella tua geometria e inserire la logica di evidenziazione nel tuo shader di frammenti. Ciò è estremamente utile quando non si desidera avere due copie di dati in memoria e si avrà un maggiore controllo sull'implementazione dell'evidenziazione.

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.