9.5. Sfocatura radiale

0
Il tuo voto: Nessuno

Questo effetto implementa una sfocatura la cui intensità è determinata dalla distanza da un punto di origine specificato dall'utente che risulta a fuoco. Per fare in modo che la sfocatura risulti di tipo radiale è necessario che i campionamenti dei texels necessari a calcolare il colore di un determinato pixel vengano effettuati lungo la direzione che passa per l'origine specificata e il pixel stesso.

Nel codice HLSL sottostante sono state dichiarate diverse variabili che rendono l'utilizzo dell'effetto plù adattabile possibile: Density controlla in modo lineare la luminescenza dei campioni, Exposure controlla linearmente l'intensità globale, Weight modula l'intensità del decadimento, Decay controlla in modo esponenziale la trasparenza dei campioni. 

La definizione NUM_SAMPLES specifica il numero di campionamenti per pixel; sotto un certo limite è possibile applicare lo shader ad uno Shader Model 2.0 con una resa grafica peggiore, con l'impostazione specificata è necessario uno Shader Model 3.0. Nello specificare un valore per questa definizione è bene utilizzare quelli che sono potenze di 2 (2n).

  1 #define NUM_SAMPLES 128
  2 
  3 sampler2D frameSampler;
  4 
  5 // Controllo sulla densità
  6 uniform float Density;
  7 // Controllo generale sulla luminosità della luce generata
  8 uniform float Exposure;
  9 // Controllo sull'intensità
 10 uniform float Weight;
 11 // Controllo sul decadimento
 12 uniform float Decay;
 13 // Posizione della sorgente luminosa in screen-space
 14 uniform float2 ScreenLightPos;
 15 
 16 float4 ps_main(float2 texCoord : TEXCOORD0) : COLOR0
 17 {
 18     // Calcola il vettore dal pixel corrent al punto di fuoco
 19     half2 deltaTexCoord = (texCoord - ScreenLightPos);
 20 
 21     // Divide per il numero di campioni
 22     deltaTexCoord *= 1.0f / NUM_SAMPLES * Density;
 23 
 24     // Recupera il campione iniziale
 25     half3 color = tex2D(frameSampler, texCoord);
 26 
 27     // Imposta il fattore di decadimento
 28     half illuminationDecay = 1.0f;
 29 
 30     // Esegue NUM_SAMPLES iterazioni lungo la direzione deltaTexCoord
 31     for (int i = 0; i < NUM_SAMPLES; i++)
 32     {
 33         // Calcola la posizione successiva lungo la direzione
 34         texCoord -= deltaTexCoord;
 35 
 36         // Recupera il colore della nuova posizione
 37         half3 sample = tex2D(frameSampler, texCoord);
 38 
 39         // Applica l'attenuazione e l'intensità
 40         sample *= illuminationDecay * Weight;
 41 
 42         // Accumula col colore iniziale
 43         color += sample;
 44 
 45         // Aggiorna il fattore di decadimento esponenziale
 46         illuminationDecay *= Decay;
 47     }
 48 
 49     // Calcola il colore finale aggiungendo al colore del pixel
 50     // corrente quello calcolato lungo la direzione specificata
 51     // e riscala per l'esposizione.
 52     return float4(color * Exposure, 1);
 53 }

Questo post-processo è utile in molteplici utilizzi nel gameplay come: attirare l'attenzione del giocatore in un punto specifico dello schermo, simulare alte velocità nei giochi di guida, realizzare visivamente i colpi subiti nei giochi di tipo FPS, ecc..

Utilizzando una texture specifica in luogo del back-buffer è utile, nel rendering di ambienti aperti, per rappresentare l'illuminazione del pulviscolo atmosferico da parte del sole; in questo caso il punto di origine è la posizione in screen-space del sole. Questa soluzione non è fisicamente corretta, tuttavia le imprecisioni non sono individuabili se la scena è in movimento ed è di media complessità.

La texture necessaria all'implementazione del secondo effetto viene creata renderizzando normalmente lo skybox e successivamente mascherandolo con le sole sagome nere degli oggetti che fanno da occlusori come edifici, alberi, terreno, ecc... come visibile di seguito:

Nell'immagine precedente è possibile osservare come il raggio di luce che passa tra il fianco ed il braccio del modello sia realizzato in modo corretto.