• Non ci sono risultati.

Nel par. 2.1.5 abbiamo discusso in maniera approfondita delle tecniche di image- based lighting (IBL) arrivando anche a dare una formula per l'illuminazione di un punto P sulla base di una coppia di immagini usate per l'illuminazione della scena (diuse cube environment map e specular cube environment map).

L'applicazione dell'illuminazione basata su immagini non dipende dal tipo par- ticolare di oggetto che si sta disegnando: mentre l'utilizzo dello shader program per il normal mapping (ad esempio) è legato al particolare oggetto virtuale (che deve possedere i parametri necessari), l'environment mapping è una modalità alternativa all'illuminazione diretta tradizionale e dipende dalla congurazione della scena (può anche venire disattivato e riattivato più volte durante l'esecuzione).

Quando si ha a che fare con oggetti light mapped, tutte le informazioni di illumi- nazione sono statiche e ricavabili dalla light map, ma in tutti gli altri casi dobbiamo fare in modo che gli shader program utilizzati per il rendering funzionino anche nel caso di environment mapping (oltre che nel caso di illuminazione diretta).

L'environment mapping consiste semplicemente in un diverso calcolo da compie- re nello stadio di fragment processing sulla base dei valori ricavati dalle cube map. I vertex shader presentati nelle precedenti sezioni di questo capitolo rimangono per- tanto validi, mentre i fragment shader visti in precedenza (escludendo il caso di light mapping) sono incompleti in quanto è necessario aggiungere una nuova modalità di funzionamento in ognuno di essi che esegua i calcoli di illuminazione in accordo alla tecnica di environment mapping (eq. 2.3).

Quello che si fa è allora introdurre una variabile uniform per discriminare la modalità di illuminazione diretta dall'IBL, e sulla base del suo valore si calcola il vettore fragColorRGB in modo opportuno (Phong reection model o equazione 2.3). Nel caso in cui venga richiesto environment mapping, si invoca una funzione per il calcolo del vettore fragColorRGB.

La funzione per il calcolo dell'illuminazione secondo l'algoritmo di environment mapping è stata scritta in un fragment shader separato ed ha la seguente forma:

# version 330 core // GLSL version 3.30 , core OpenGL profile

uniform mat4 normalMatrix ; // matrix for normals ( obj -> wrld space ) uniform mat4 modelMatrix ; // modeling matrix ( obj -> wrld space ) uniform vec3 matDiffuse ; // material diffuse color

uniform vec3 eyePosObj ; // eye position in world coordinates uniform int envMode ; // environment mapping mode

uniform samplerCube envDiffSampler ; // diffuse environment map sampler uniform samplerCube envSpecSampler ; // specular environment map sampler smooth in vec3 fragPositionObj ;

vec3 ComputeIBL ( vec3 normalObj ) { vec3 retVal = vec3 (0.0 , 0.0 ,0.0);

vec3 normalWorld = ( normalMatrix * vec4 ( normalObj ,0.0)). xyz ; if( ( envMode & 0 x0001 ) != 0) { // diffuse environment map active

retVal += matDiffuse * texture ( envDiffSampler , normalWorld ). rgb ; }

if( ( envMode & 0 x0002 ) != 0) { // specular environment map active vec3 eye = normalize ( eyePosObj -

( modelMatrix * vec4 ( fragPositionObj ,1.0)). xyz ); vec3 cubeCoord = reflect (-eye , normalWorld );

retVal += matSpecular * texture ( envSpecSampler , cubeCoord ). rgb ; }

return retVal ; }

dove notiamo che:

• La variabile uniform intera envMode determina il tipo di illuminazione con cui si ha a che fare: 0 signica che non si sta facendo environment mapping, se la diuse cube environment map è attiva avremo il bit meno signicativo ad 1, e se la specular cube environment map è disponibile avremo il secondo bit meno signicativo ad 1. Quando una delle due mappe manca, il relativo termine nella eq. 2.3 viene considerato nullo.

• Per accedere alle cube map si usano (come accennato nel par. 2.1.5) vettori a tre componenti (s, r, t) che vanno pensati applicati nel centro del cubo; non si usano più le coordinate ordinarie (u, v) come nel caso di accesso a texture bidimensionali.

• Manca il termine relativo al colore emissivo del materiale che si nota in eq. 2.3: questo viene inserito prima di chiamare la ComputeIBL() ed è sempre un semplice parametro additivo.

• L'accesso alla diuse cube environment map avviene (come stabilito dall'equa- zione 2.3) tramite la normale nel frammento. Questa normale dipende dal tipo di shading utilizzato (normal mapping o Phong interpolation di base) e viene

CAPITOLO 4. REALIZZAZIONE DELLE TECNICHE PRESENTATE 117 ricevuta dalla funzione come parametro (in object coordinates). La normale deve essere trasformata in world coordinates prima di venire utilizzata per accedere alla diuse environment map e questa operazione avviene per mezzo della matrice normalMatrix.

• L'accesso alla specular cube environment map avviene (come stabilito dal- l'equazione 2.3) in una direzione dettata dalla riessione del vettore che va dalla posizione dell'osservatore al frammento considerato (ovviamente consi- derato in world coordinates). La variabile uniform eyePosObj contiene infatti in questo fragment shader la posizione dell'osservatore in world coordinates, si usa il nome eyePosObj per riutilizzare la variabile uniform che nel caso di illuminazione diretta contiene la posizione della telecamera in object space. • La trasformazione in world space della posizione del vertice e della normale

aggiunge un costo a questa procedura derivante dal fatto che tutte le altre operazioni avvengono in object space. Questo è lo svantaggio che si aronta lavorando in object coordinates, ma ricordiamo che lavorando in world space otterremmo altri svantaggi in altre situazioni di shading (ad esempio in caso di normal mapping).

Notare che per trasformare le normali in world space non abbiamo usato la matrice di modeling modelMatrix, ma ci siamo invece adati alla matrice (potenzialmente diversa) normalMatrix. Questo deriva dal fatto che se la modeling matrix contiene dei cambiamenti di scala il vettore che ricaviamo trasformando la normale mediante la modelMatrix è diverso dal vettore normale in world space: potremmo ottenere un vettore alterato con una direzione diversa da quella originale (se prima ad esempio la normale era ortogonale alla supercie, dopo la moltiplicazione per la matrice di modeling potrebbe non esserlo più). Per trasformare i vettori normali in world space è in realtà necessario utilizzare una matrice diversa:

Mnormal= Mmodeling−1

T

I fragment shader visti in precedenza devono essere modicati per sfruttare i servizi oerti dalla funzione ComputeIBL() nel caso in cui si stia facendo environment mapping. La modica introduce semplicemente un salto condizionale sulla base della nuova variabile uniform, come segue:

...

uniform int envMode ; // environment mapping mode ...

out vec4 fragColor ; // resulting fragment color ( with alpha ) vec3 ComputeIBL ( vec3 normalObj ); // function declaration void main ( void ) {

...

vec3 fragColorRGB = matEmission ; ...

if( envMode == 0) { // no environment mapping [ USUAL SHADING ]

} else { // environment mapping fragColorRGB += ComputeIBL (N); }

fragColor *= vec4 ( fragColorRGB ,1.0); }

Dunque se si utilizza illuminazione diretta (envMode = 0) si entra nel primo ramo del costrutto if, che contiene le istruzioni per lo shading come descritto nelle precedenti sezioni di questo capitolo.

Il fragment shader contenente la funzione ComputeIBL() e quello classico modi- cato come sopra verranno compilati e collegati insieme in un unico fragment shader executable da eseguire nello stadio di fragment processing (come se si trattasse di un singolo fragment shader).

Il modo in cui opera la funzione ComputeIBL() risulta valido anche nel caso di environment map ad elevato range dinamico (HDR). L'utilizzo di immagini HDR garantisce che non si presenteranno artefatti dovuti alla non linearità della codica e che avremo un calcolo molto preciso dei valori di illuminazione (par. 2.1.5). È importante notare però che non si applicano particolari operatori di tone mapping e non si sfruttano eetti realizzati in un nuovo passo di rendering. Ci si ada invece alle operazioni di base OpenGL per eettuare il mapping sul ridotto range dinamico del display (per cui l'immagine non risulterà molto diversa da quella ottenuta con illuminazione non HDR).