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.