Come posso raytrace una scena che non si adatta alla memoria?


11

Se la scena da raytracing non può essere archiviata in memoria, quindi senza aggiungere più RAM alla macchina sembra irrealistico renderla in un arco di tempo pratico, a causa della necessità di caricare diverse parti della scena dal disco potenzialmente più volte per pixel .

C'è un modo per aggirare questo? Sto cercando di pensare a un modo per eseguire contemporaneamente un gran numero di calcoli che coinvolgono un particolare sottoinsieme della scena, per ridurre il numero di volte che deve essere caricato in memoria. Esiste un altro modo per migliorare la velocità in questo caso?

Risposte:


10

Se la scena non si adatta interamente alla memoria, stai entrando nel campo del rendering non core. Ci sono essenzialmente due approcci qui: a) Genera la tua scena su richiesta b) Carica la tua scena su richiesta

Il primo approccio si allinea bene con la maggior parte dei flussi di lavoro di animazione, in cui i modelli sono fortemente suddivisi usando ad esempio Catmull-Clark e possono diventare molto intensi in termini di memoria, ma le mesh di base si adattano facilmente alla memoria. Pixar ha alcuni articoli su questo (ad esempio Ray Differentials e Multiresolution Geometry Caching per Distribution Ray Tracing in scene complesse ), ma l'essenza di ciò è che i modelli vengono suddivisi solo quando vengono colpiti da un raggio e suddivisi solo quanto è ragionevole per un raggio del genere (ad es. l'interreflessione diffusa richiede meno precisione rispetto ai riflessi dello specchio). Il resto è gestito da una cache geometrica, che mantiene in memoria i modelli suddivisi e, si spera, rende il processo efficiente mediante una buona strategia di sfratto.

Fintanto che tutte le mesh di base si adattano comodamente alla memoria, è possibile uscire facilmente dal core e renderizzare mesh a livelli di suddivisione che non si adattano mai alla memoria. La cache della geometria si ridimensiona bene anche con la quantità di memoria che hai, permettendoti di pesare la RAM rispetto ai tempi di rendering. Questo è stato utilizzato anche in auto credo.

Il secondo approccio è più generale e non si basa sull'uso pesante della suddivisione. Invece, si basa sul fatto che la tua scena è stata molto probabilmente realizzata da un artista e viene già suddivisa in oggetti ragionevolmente piccoli che si adattano alla memoria individualmente. L'idea è quindi quella di mantenere due gerarchie (kD-tree o gerarchia del volume di delimitazione): una gerarchia di livello superiore che archivia solo i riquadri di delimitazione degli oggetti nella scena e una gerarchia di basso livello che memorizza la geometria effettiva. Esiste una tale gerarchia di basso livello per ciascun oggetto.

In questo approccio, idealmente già memorizzi un rettangolo di selezione insieme a ciascun oggetto sul disco. Man mano che la scena viene caricata, inizialmente costruisci solo la gerarchia di livello superiore, il che significa che devi solo guardare le finestre di delimitazione e non la geometria. Quindi inizi a tracciare i raggi e attraversali attraverso la gerarchia. Ogni volta che un raggio colpisce un nodo foglia nella gerarchia di livello superiore (ovvero colpisce il riquadro di delimitazione di un oggetto), quell'oggetto viene caricato in memoria e viene costruita la sua gerarchia di livello inferiore. Il raggio continua quindi a rintracciare quell'oggetto. Combinato con una cache di oggetti che mantiene il più possibile la memoria della gerarchia di basso livello, ciò può comportare ragionevolmente bene.

Il primo vantaggio di un tale approccio è che gli oggetti che non vengono mai colpiti non vengono mai caricati, il che significa che si adatta automaticamente alla visibilità della scena. Il secondo vantaggio è che se si tracciano molti raggi, non è necessario caricare immediatamente un oggetto quando viene colpito da un raggio; invece, puoi tenere quel raggio e attendere che abbastanza raggi abbiano colpito quell'oggetto, ammortizzando il carico su più raggi.

È inoltre possibile combinare questo approccio con un algoritmo di ordinamento dei raggi come Ombreggiatura differita ordinata per tracciamento del percorso di produzione per evitare il thrashing dovuto a raggi incoerenti. L'articolo citato descrive l'architettura del renderizzatore Disney Hyperion, usato per Big Hero 6 credo, quindi molto probabilmente può gestire scene su scala di produzione.


1
Questo è super interessante! Così è il documento Disney che hai collegato.
John Calsbeek,

+1 Così tante risposte a cose che mi sono sempre chiesto!
Rotem,

7

Se organizzi la tua scena in una struttura spaziale (il solito modo è una Gerarchia del volume vincolante ), puoi usare una sorta di scena virtuale (sto inventando questo termine, in riferimento alle trame virtuali ).

Un gestore di memoria manterrebbe caricato solo un numero limitato di caselle di delimitazione alla volta e astrarre l'operazione che consiste nel recupero di una.

In questo modo, una casella verrebbe caricata solo se necessario: quando un raggio colpisce una casella di delimitazione, la casella viene caricata per risolvere la collisione. Successivamente, quando è necessario caricare un'altra casella, quella inutilizzata viene eliminata per fare spazio a quella nuova.

Con tutte queste caselle caricate ed eliminate, la coerenza del raggio sarebbe un fattore importante nella velocità. Suppongo che un ulteriore miglioramento potrebbe essere quello di rinviare il caricamento, riordinando i raggi per trattare prima le scatole già caricate.


Sì qualcosa del genere.
joojaa,

1

Quello che fai è caricare triangoli in memoria dal disco in base a ciò che è stato colpito in precedenza. Puoi iniziare con i triangoli nelle immediate vicinanze. Il ragionamento è che in una zona è probabile che i raggi colpiscano ripetutamente gli stessi triangoli. E alla fine sarai in qualche modo efficiente. (Per questo motivo è una buona idea memorizzare nella cache il triangolo dell'ultimo colpo nella traccia dell'occlusione che non interessa l'ordine)

In secondo luogo, i triangoli vengono archiviati in un albero spaziale che consente di effettuare ricerche rapide dal disco, per rinnovare le porzioni che si hanno in memoria per prossimità. Quindi carica solo i rami che si frappongono al raggio. Se è una specie di albero di voxel, come un ottetto, puoi persino ordinare i raggi secondari e risolverli per coerenza. Un albero BSP è anche un po 'bravo nelle aree di potatura.

Ci sono casi in cui questo fallisce ma è ragionevolmente efficace nella maggior parte dei bucket di scena se non si esegue il rendering del rumore ...

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.