Ci sono molti modi per farlo. Ciò richiederà l'uso di uno shader e presumo che tu stia già facendo l'illuminazione per pixel. Di seguito sono riportati alcuni suggerimenti, tuttavia trovare la tecnica giusta per te potrebbe richiedere molte più ricerche.
Veloce e sporco
È possibile specificare i riquadri di delimitazione che definiscono le aree interne. Se la luce è fuori dalle scatole, ma la geometria (che non è in ombra) è dentro la scatola, allora la luce deve essere stata influenzata dal passaggio attraverso una finestra (questo è vero anche se la geometria è fuori dalla scatola e la luce è dentro). L'unico problema qui è come passare le informazioni sulla scatola allo shader e come dichiarare l'effetto sulla luce.
Un'altra opzione è quella di specificare le finestre come oggetti che giacciono sui piani. Prima prova per vedere se la geometria e la luce sono sui lati opposti del piano e poi se la strada tra loro interseca il piano in un punto all'interno dei confini della finestra. Questo sarebbe più preciso del primo metodo e sarebbe più facile avere finestre negli stessi interni con diversi colori del vetro.
Continua a essere più dettagliato con la rappresentazione geometrica delle finestre e otterrai risultati più accurati, ma anche il calcolo diventerà più pesante.
Queste tecniche funzionerebbero ragionevolmente bene per uno sparatutto in corridoio, ma non così bene per un mondo dinamico o aperto, poiché probabilmente sarebbe necessario un sacco di modifiche per farlo sembrare giusto senza troppi artefatti. Inoltre, queste tecniche potrebbero rapidamente diventare un po 'intense, quindi sarebbe consigliabile passare a una pipeline di ombreggiatura differita.
Mappe d'ombra
Un'altra opzione è fare qualcosa di simile alla mappatura dell'ombra.
Nella mappatura dell'ombra si genera un'immagine bitmap del mondo interessato da una luce. Ogni pixel, pur rimanendo un colore, è in realtà la distanza del pezzo più vicino di geometria non trasparente (si utilizzano i quattro byte per 1 float anziché 4 colori). Se calcoli la distanza dalla luce a un pezzo di geometria ed è oltre il valore corrispondente nella mappa d'ombra, il tuo pezzo di geometria è in ombra (generalmente usi il raggio tra la geometria e la luce per indicizzare la mappa).
Se applichi questa idea al tuo problema, ciò che faresti è memorizzare una mappa della distanza dalla luce del pezzo più vicino di geometria trasparente, quindi creare anche una seconda mappa del colore della luce dopo aver attraversato quella geometria ( semplicemente il colore della geometria se la luce è bianca).
Se il tuo pezzo di geometria è più lontano della distanza in questa mappa, usa il colore della mappa, se non lo è, usa il colore chiaro originale.
La funzione per il calcolo del colore per ciascun pixel nella mappa dovrebbe essere approssimativamente; lightColor - invertedWindowColor. Quindi per una luce bianca pura e una finestra rossa pura che non assorbe nessuno dello spettro rosso che otteniamo; (255.255.255) - (0,255.255) = (255,0,0). Quindi il colore della luce sull'altro lato è rosso puro. Per un oggetto trasparente più complesso, come una finestra di vetro colorato, potresti desiderare una ricerca di trama per ottenere il colore del materiale.
Se stai cercando qualcosa di simile, dai un'occhiata a Reflective Shadow Maps .
Questa tecnica offre una grande fedeltà e sarebbe probabilmente la migliore se si desidera utilizzare geometrie trasparenti complesse come le vetrate.
Tentativo di una soluzione generale
Recentemente è diventato popolare codificare le informazioni di illuminazione in una rappresentazione voxel (non sono solo per la geometria). L'ultimo motore Crytek utilizza questo tipo di stratagemma per l'illuminazione avanzata ( volumi di propagazione della luce ).
Ecco l'idea generale:
- Crea una mappa di cubi con spaziatura uniforme che racchiuda la scena (considera l'utilizzo di curve di ordine z ).
- Trova un modo per memorizzare le informazioni sull'illuminazione degli incidenti per ciascun voxel (qui sono utili rappresentazioni armoniche sferiche).
- Trova il voxel contenente una luce e rappresenta quella luce nel voxel.
- Propaga la luce verso l'esterno attraverso i voxel adiacenti (un po 'come l'acqua di Minecraft)
- Calcola in che modo la geometria di ciascun voxel influirà sulla luce che la attraversa (assorbi, rifletti, trasmetti)
- ripetere fino a quando la luce si è sbiadita
Esistono molti modi per creare queste informazioni voxel, ma l'elenco sopra fornisce un'idea generale. Per esempio; puoi iniziare generando mappe / volumi ombra e quindi proiettando tali informazioni nella mappa voxel in modo da poter creare rapidamente la mappa di illuminazione diretta. Quindi si avvia la propagazione dai voxel lungo il bordo dell'area interessata. Tieni presente che, in questo caso, vorrai ignorare se la geometria è trasparente o meno durante la generazione della mappa / volume dell'ombra.
Nel passaggio finale di un renderer differito, quando si calcola l'illuminazione di un punto della geometria, è sufficiente utilizzare la posizione della geometria per indicizzare la mappa del voxel per scoprire com'è l'illuminazione incidente in quel punto nello spazio. Quindi è possibile creare una mappa dello schermo di illuminazione incidente lato cpu o eventualmente farlo con cuda.