by Luca Sorace 1910722
Volumetric material
Ho scelto questo extra credit difficile poiché irl lavoro come tecnico luci, quindi so già abbastanza bene come funzionano i fumi nella vita reale :)
Quando un fotone entra all’interno di un fumo, c’è una probabilità che colpisca una particella (Che nella realtà potrebbe essere ad esempio polvere, cenere, vapori a base d’acqua (faze) o olio (haze), etc). In caso di hit, c’è una possibilità (In base a quanto è “forte” il fascio di luce e quanto denso è il fumo) che il fotone venga assorbito, oppure che venga deviato in una direzione casuale. Nella realtà, specie con i vapori acquei, è molto probabile che il raggio del fotone venga deviato di “poco” rispetto alla direzione originale. Da qui abbiamo l’effetto in cui un fascio di luce che si dirige verso l’osservatore (O che passa laterale a lui) risulta molto più visibile rispetto allo stesso fascio di luce, ma visto “da dietro”.
(Vedi le foto sottostanti, dove si nota come partendo alle spalle della fonte luminosa e girandola man mano fino ad arrivarle davanti, la luminosità che percepiamo del fascio di luce proiettato in aria aumenta notevolmente, arrivando a saturare il sensore della fotocamera!)
Algoritmo
Alla mia funzione ricorsiva che si occupa di processare i volumi, viene inizialmente passato un nuovo raggio, con la stessa direzione di quello originale, ma che come origine ha il punto in cui abbiamo hittato le mash del volume. A questo punto il mio algoritmo:
- Calcola il prossimo hit del raggio in input con una qualsiasi mash
- Si calcola la distanza D tra l’origine del raggio e questo ultimo hit. Tale distanza rappresenta quindi “quanto manca” alla fine del volume in cui il nostro raggio si trova
- Si genera la distanza D’ per la prossima deviazione del raggio utilizzando la seguente formula:
(-1 / d) * log(rand1f())
, dove d è la densità (ior) del volume
- Se
D' > D
vuole dire che il fotone del nostro raggio sta rimbalzando su una particella interna al volume stesso
- aggiorniamo il punto di origine del nostro raggio
- generiamo una nuova direzione casuale (Leggere il punto sotto per quanto concerne la generazione della direzione casuale)
- andiamo avanti nella ricorsione
- Altrimenti, controlliamo quale sia l’istanza su cui abbiamo hittato
- Se è l’istanza di partenza vuol dire che il fotone sta uscendo dal volume
- chiamiamo normalmente
shade_raytrace()
per proseguire il raytracing verso i prossimi oggetti
- Se non è l’istanza di partenza, vuol dire che stiamo colpendo un oggetto intersecato nel nostro volume
- Gestiamo quindi l’hit in base al tipo di materiale che abbiamo colpito, in maniera simile a come facciamo dentro
shade_raytrace()
. Se il tipo del materiale è di nuovo volumetric
, vuol dire che abbiamo colpito un volume dentro al nostro volume. Ricominciamo quindi la ricorsione però avendo come istanza, densità, colore e raggio di partenza, quelli di questo ultimo hit
- Dopo il rimbalzo sull’oggetto interno, continuiamo la ricorsione normalmente
Immagine di test
Il cubo a sinistra ha ior (densità) pari a 2, quello a destra pari a 8
L’immagine è stata renderizzata con 4096 sample, risoluzione pari a 512x512, 64 bounce e sample_shpere()
come funzione per generare la direzione casuale ad ogni scutter dei fotoni
Poiché, come scritto sopra, sono un tecnico luci, ho voluto creare una scena che emulasse quello che noi facciamo sempre: proiettare beam di luce dentro il fumo. Sarò onesto, prima di creare questa scena ero veramente tanto curioso di vedere come sarebbe uscita fuori.
Ho voluto ricreare la seguente situazione molto semplice:
Una luce, generata dentro una lampada, viene proiettata in un fascio stretto di tipo “wash” nel fumo. Per fare questo abbiamo bisogno di una fonte di luce che viene “arginata” in uno spazio chiuso e vuoto (idealmente deve essere convesso per fare muovere tutta la luce verso la direzione corretta). Tale spazio dovrà essere dotato di un “qualcosa” che sagomi la luce in uscita in un beam stretto, in modo che sia più facile notarlo nell’aria.
Ecco le foto dal vivo, che fanno capire in maniera più semplice cosa sto realizzando:
Dove evidenziati in azzurro c’è la fonte di luce, in blu il beam di luce, in rosso le pareti dello “spazio chiuso”, in arancione le flag per sagomare il fascio di luce in uscita
Ho quindi ricreato nel progetto una situazione analoga a quella dal vivo: Ho preso una luce e l’ho chiusa dentro un cubo vuoto. Tale cubo ha un piccolo buco su uno dei lati, in modo che la luce possa uscire come beam solamente da lui. Il tutto si trova dentro un cubo molto grande fatto di fumo, che ci permette di visualizzare il beam di luce nell’aria.
Nella prima immagine, la posizione della luce. Nella seconda la luce dentro il cubo (Reso trasparente per maggiore visibilità). Nella terza il cubo ed la luce all’interno del fumo (Colorato di verde con superfici matte e trasparenti per maggiore visibilità)
Ecco i risultati di quanto ottenuto:
Sample: 50000, bounces: 64, risoluzione: 800x333, funzione per la generazione di una direzione casuale: sample_hemisphere_cospower(4)
, ior (densità) del fumo: 0.4
Sample: 50000, bounces: 64, risoluzione: 800x333, funzione per la generazione di una direzione casuale: sample_hemisphere_cospower(4)
, ior (densità) del fumo: 2
Ecco invece come appare nella vita reale:
Generazione della direzione casuale
Anche se nel corso ci è stato detto di usare sample_sphere()
, come ho mostrato sopra, nella realtà i raggi, quando scatterano, tendono a non deviarsi tanto dalla direzione originale. Per questo motivo all’eseguibile ho aggiunto un nuovo argomento, fogprocesspowtype
, intero, che ci permette di scegliere quale funzione usare per generare la nuova direzione. I valori possibili sono:
Valore |
Funzione |
< 0 |
sample_sphere() |
== 0 |
sample_hemisphere_cos(d) con d = alla direzione precedente del raggio |
> 0 |
sample_hemisphere_cospower(p, d) con d = alla direzione precedente del raggio e p = al valore dato in input a fogprocesspowtype |
Questi sono i risultati:
Renderizzati tutti con 50000 samples, 64 bounce e una risoluzione pari a 360x150p
Interessante notare come, per quanto una diffusione troppo “smarmellata” delle direzioni casuali sia errata (sample_sphere()
), lo è anche una diffusione generata dentro l’area di coni molto stretti (sample_hemisphere_cospower(64)
). Più saliamo di potenza in sample_hemisphere_cospower()
e più il beam scompare dal volume a noi osservatori posizionati a circa 45° dall’origine della luce. Il motivo è molto semplice: poiché siamo laterali rispetto alla direzione della luce, con coni molto stretti è quasi impossibile che i fotoni riescano a deviare al punto da “collegare” la camera alla fonte luminosa
Questo va quindi a creare una serie di angolazioni che rendono il nostro algoritmo sbagliato. Se usiamo angoli troppo piccoli, i fotoni non raggiungeranno mai la camera (anche se dovrebbero), se usiamo angoli troppo grandi, i fotoni raggiungono la camera da direzioni sbagliate, fin troppo spesso da dietro la fonte di luce
Reference
CG HW2: Extra material
by Luca Sorace
1910722
Volumetric material
Ho scelto questo extra credit difficile poiché irl lavoro come tecnico luci, quindi so già abbastanza bene come funzionano i fumi nella vita reale :)
Quando un fotone entra all’interno di un fumo, c’è una probabilità che colpisca una particella (Che nella realtà potrebbe essere ad esempio polvere, cenere, vapori a base d’acqua (faze) o olio (haze), etc). In caso di hit, c’è una possibilità (In base a quanto è “forte” il fascio di luce e quanto denso è il fumo) che il fotone venga assorbito, oppure che venga deviato in una direzione casuale. Nella realtà, specie con i vapori acquei, è molto probabile che il raggio del fotone venga deviato di “poco” rispetto alla direzione originale. Da qui abbiamo l’effetto in cui un fascio di luce che si dirige verso l’osservatore (O che passa laterale a lui) risulta molto più visibile rispetto allo stesso fascio di luce, ma visto “da dietro”.
(Vedi le foto sottostanti, dove si nota come partendo alle spalle della fonte luminosa e girandola man mano fino ad arrivarle davanti, la luminosità che percepiamo del fascio di luce proiettato in aria aumenta notevolmente, arrivando a saturare il sensore della fotocamera!)
Algoritmo
Alla mia funzione ricorsiva che si occupa di processare i volumi, viene inizialmente passato un nuovo raggio, con la stessa direzione di quello originale, ma che come origine ha il punto in cui abbiamo hittato le mash del volume. A questo punto il mio algoritmo:
(-1 / d) * log(rand1f())
, dove d è la densità (ior) del volumeD' > D
vuole dire che il fotone del nostro raggio sta rimbalzando su una particella interna al volume stessoshade_raytrace()
per proseguire il raytracing verso i prossimi oggettishade_raytrace()
. Se il tipo del materiale è di nuovovolumetric
, vuol dire che abbiamo colpito un volume dentro al nostro volume. Ricominciamo quindi la ricorsione però avendo come istanza, densità, colore e raggio di partenza, quelli di questo ultimo hitImmagine di test
Il cubo a sinistra ha ior (densità) pari a 2, quello a destra pari a 8
L’immagine è stata renderizzata con 4096 sample, risoluzione pari a 512x512, 64 bounce e
sample_shpere()
come funzione per generare la direzione casuale ad ogni scutter dei fotoniScena extra
Poiché, come scritto sopra, sono un tecnico luci, ho voluto creare una scena che emulasse quello che noi facciamo sempre: proiettare beam di luce dentro il fumo. Sarò onesto, prima di creare questa scena ero veramente tanto curioso di vedere come sarebbe uscita fuori.
Ho voluto ricreare la seguente situazione molto semplice:
Una luce, generata dentro una lampada, viene proiettata in un fascio stretto di tipo “wash” nel fumo. Per fare questo abbiamo bisogno di una fonte di luce che viene “arginata” in uno spazio chiuso e vuoto (idealmente deve essere convesso per fare muovere tutta la luce verso la direzione corretta). Tale spazio dovrà essere dotato di un “qualcosa” che sagomi la luce in uscita in un beam stretto, in modo che sia più facile notarlo nell’aria.
Ecco le foto dal vivo, che fanno capire in maniera più semplice cosa sto realizzando:
Dove evidenziati in azzurro c’è la fonte di luce, in blu il beam di luce, in rosso le pareti dello “spazio chiuso”, in arancione le flag per sagomare il fascio di luce in uscita
Ho quindi ricreato nel progetto una situazione analoga a quella dal vivo: Ho preso una luce e l’ho chiusa dentro un cubo vuoto. Tale cubo ha un piccolo buco su uno dei lati, in modo che la luce possa uscire come beam solamente da lui. Il tutto si trova dentro un cubo molto grande fatto di fumo, che ci permette di visualizzare il beam di luce nell’aria.
Nella prima immagine, la posizione della luce. Nella seconda la luce dentro il cubo (Reso trasparente per maggiore visibilità). Nella terza il cubo ed la luce all’interno del fumo (Colorato di verde con superfici matte e trasparenti per maggiore visibilità)
Ecco i risultati di quanto ottenuto:
Sample: 50000, bounces: 64, risoluzione: 800x333, funzione per la generazione di una direzione casuale:
sample_hemisphere_cospower(4)
, ior (densità) del fumo: 0.4Sample: 50000, bounces: 64, risoluzione: 800x333, funzione per la generazione di una direzione casuale:
sample_hemisphere_cospower(4)
, ior (densità) del fumo: 2Ecco invece come appare nella vita reale:
Generazione della direzione casuale
Anche se nel corso ci è stato detto di usare
sample_sphere()
, come ho mostrato sopra, nella realtà i raggi, quando scatterano, tendono a non deviarsi tanto dalla direzione originale. Per questo motivo all’eseguibile ho aggiunto un nuovo argomento,fogprocesspowtype
, intero, che ci permette di scegliere quale funzione usare per generare la nuova direzione. I valori possibili sono:sample_sphere()
sample_hemisphere_cos(d)
con d = alla direzione precedente del raggiosample_hemisphere_cospower(p, d)
con d = alla direzione precedente del raggio e p = al valore dato in input afogprocesspowtype
Questi sono i risultati:
Renderizzati tutti con 50000 samples, 64 bounce e una risoluzione pari a 360x150p
Interessante notare come, per quanto una diffusione troppo “smarmellata” delle direzioni casuali sia errata (
sample_sphere()
), lo è anche una diffusione generata dentro l’area di coni molto stretti (sample_hemisphere_cospower(64)
). Più saliamo di potenza insample_hemisphere_cospower()
e più il beam scompare dal volume a noi osservatori posizionati a circa 45° dall’origine della luce. Il motivo è molto semplice: poiché siamo laterali rispetto alla direzione della luce, con coni molto stretti è quasi impossibile che i fotoni riescano a deviare al punto da “collegare” la camera alla fonte luminosaQuesto va quindi a creare una serie di angolazioni che rendono il nostro algoritmo sbagliato. Se usiamo angoli troppo piccoli, i fotoni non raggiungeranno mai la camera (anche se dovrebbero), se usiamo angoli troppo grandi, i fotoni raggiungono la camera da direzioni sbagliate, fin troppo spesso da dietro la fonte di luce
Reference