5.4. Spot

5
Il tuo voto: Nessuno Media: 5 (1 vote)

Una sorgente luminosa di tipo spot presenta tutte le caratteristiche di quella di tipo omnidirezionale ma aggiunge la definizione di un angolo che rappresenta l'ampiezza del cono di luce e da un vettore che rappresenta la direzione. Questo tipo di sorgente è utile per illuminazioni locali in cui la sorgente luminosa è parzialmente occlusa da un supporto ad esempio (illuminazione stradale, lampade, ecc...).

L'equazione che permette di distinguere se un punto da illuminare è dentro o fuori dal cono viene risolta tramite la matematica vettoriale secondo cui il coseno dell'angolo tra due vettori è uguale al prodotto scalare dei vettori stessi; applicando a questo risultato l'arco coseno possiamo determinare l'angolo presente in radianti. I vettori da prendere in considerazione per questo calcolo sono quello che definisce la direzione dello spot e l'inverso del vettore illuminazione.

nelCono = acos(LightVec · -lightDir) < (lightCone * 0.5)

Nell'HLSL, come è possibile notare, è consentito l'utilizzo di espressioni condizionali all'interno di equazioni che ritornino un valore booleano. In questo caso a true corrisponde un valore di 1.0 e a false corrisponde un valore di 0.0.

  // Calcolo della distanza dalla sorgente luminosa
  float dist = length(LightVec) * 0.01;
  // Calcolo del decadimento dovuto alla distanza, in questo
  // caso rispettando la fisica, ma il decadimento può essere
  // anche lineare (1.0 / dist)
  float decay = 1.0 / (dist * dist);

  // Normalizzo i vettori provenienti dal VertexShader
  NormalVec = normalize(NormalVec);
  LightVec = normalize(LightVec);

  // Calcolo dell'angolo formato dal vettore di direzione della luce
  // e del vettore che unisce la sorgente luminosa col punto da
  // renderizzare. Trasformazione in gradi e test con l'angolo del
  // cono specificato. 0.0 se fuori dal cono dello spot altrimenti 1.0
  float cone = acos(dot(LightVec, -lightDir)) * 180.0 / PI < lightCone * 0.5;

  // Intensita secondo Lambert
  float intensity = saturate(dot(NormalVec, LightVec));

Nel codice precedente lightCone e ghtDir sono due variabili da passare allo shader che rappresentano rispettivamente la direzione dello spot e la dimensione del cono luminoso che in questo caso è in gradi sessagesimali; è ovviamente possibile utilizzare i radianti eliminando la conversione (180 / PI). La moltiplicazione per 0.5 è dovuta al fatto che il cono si estende per metà da una parte della direzione della sorgente e per metà dall'altra.

L'immagine precedente presenta una componente ambientale azzurra per evitare che il modello sia parzialmente invisibile.