Shader
# Shader

Shader (dall'inglese to shade = ombreggiare, sfumare) indica un insieme di algoritmi usati soprattutto nella computer grafica 3D che conferiscono al materiale virtuale a cui sono abbinati delle caratteristiche o proprietà che ne descrivono o ne influenzano il modo di reagire alla luce e di rendere il passaggio da un punto completamente illuminato a uno in ombra.

Lo shader è in grado di simulare al video l'aspetto del materiale virtuale in modo tale da essere il più vicino possibile a quello reale. Tecnicamente, invece che inviare poligoni o immagini a una scheda video, un'applicazione può inviare specifici piccoli programmi, che descrivono come i poligoni e le immagini contigui debbano essere processati fino alla visualizzazione su schermo. I passaggi della pipeline grafica, e in alcuni casi l'intera pipeline, vengono rimpiazzati da questi programmi.

## Aspetti teorici

Gli shader devono riprodurre il comportamento fisico del materiale che compone l'oggetto a cui sono applicati. Si può quindi creare uno shader per i metalli, uno per la plastica, uno per il vetro e così via, e riutilizzarli più volte all'interno di una scena. Una volta modellato un oggetto complesso, come può essere ad esempio una finestra, si assocerà al modello della cornice uno shader per il legno, uno per la maniglia, e uno per il vetro. La caratteristica riutilizzabilità di questo strumento è preziosa nel lavoro con la computer grafica 3D, sia in termini di tempo che di risultato finale.

Tuttavia non bisogna confondere lo shader con il materiale (in un programma di modellazione come Blender), in quanto il primo regola le proprietà ottiche dell'ombreggiatura, il secondo invece ne è il contenitore - che permette di impostare anche altri parametri oltre l'ombreggiatura della mesh, come ad esempio il colore di fondo o la trasparenza.

Per determinare l'aspetto della superficie, uno shader utilizza tecniche già consolidate come l'applicazione di texture e la gestione delle ombre. Gli shader possono anche essere usati per applicare effetti di postprocessing. Essendo programmi a tutti gli effetti, è possibile utilizzarli anche per la replicazione di eventi fisici molto complessi quali collisioni e simulazioni fluidodinamiche. Nell'ambito dell'ottica sono abitualmente usati per simulare: diffusione, riflessione, rifrazione, e dispersione della luce.

Le moderne Graphics Processing Unit dispongono di diverse pipeline adibite alla trasformazione di una scena 3D in un'immagine raster che possa essere rappresentata sullo schermo. Tali pipeline svolgono una serie di operazioni basate su shader programmabili.

Le librerie grafiche DirectX e OpenGL utilizzano tre tipologie di shader, che sfruttano le capacità di shading delle Graphics Processing Unit presenti nelle schede video. Con la decima versione delle librerie DirectX, integrate in Microsoft Windows Vista, le tre tipologie sono state riunite nell'Unified shader model, o Shader Model 4.0.

### Vertex Shader

I vertex shader sono utilizzati per manipolare i vertici, prendendo la configurazione iniziale del vertice (operando su un solo vertice per volta) e alterandola cambiandone i valori di posizione, normale, o coordinate della texture (tuttavia un vertex shader non può creare più vertici di quanti ce ne siano già). Inoltre prepara l'ambiente shader per qualunque ulteriore elaborazione dei vertici per tessellation e geometry shader e per la rasterizzazione ed elaborazione di fragment shader. Un inconveniente è rappresentato dalle normali dei vertici, dato che una volta che la geometria cambia, occorre calcolare le nuove normali del modello. Il modo in cui è possibile farlo, dipende dal modo in cui la geometria è stata definita. Qualunque cosa che richieda il movimento dei vertici, come bandiere sventolanti, vestiti ondeggianti, capelli al vento, particelle d'acqua di fontane, schizzi d'acqua, ecc... può utilizzare questo meccanismo di programmazione.

### Tessellation Shader

Premessa: Una tassellatura (in inglese tessellation), in computer grafica, è un processo che divide una superficie di una mesh, rendendola più levigata e formata da triangoli.

I tessellation shader possono opzionalmente seguire i vertex shader nella pipeline. La loro funzione principale è espandere un'originale primitiva geometrica in un insieme di primitive, che esprime la geometria con maggiore dettaglio. Introdotti con l'OpenGL 4.0, essi interpolano la geometria per crearne di addizionale, che può:

* Permettere di eseguire suddivisione adattiva basata su una varietà di criteri come la dimensione o la curvatura
* Permettere di rifinire modelli grezzi tramite la GPU, donando una specie di compressione geometrica
* Permettere di applicare dettagliate displacement map senza fornire equamente della geometria dettagliata
* Permettere di adattare la qualità visiva al livello di dettaglio richiesto
* Permettere di creare silhouette più lisce
* Permettere di eseguire lo skinning più facilmente

Tessellation Shader o Geometry Shader?

Sia i geometry shader che i tessellation shader sono capaci di creare nuova geometria da geometria esistente, ed entrambi sono utilizzati per fornire supporto per il livello di dettaglio, quindi potrebbe esserci confusione sul quando usare un tipo o l'altro. Mentre le capacità di ognuno sono in qualche modo simili, ci sono differenze distintive.

Un tessellation shader crea molta geometria, ma tutta la nuova geometria è dello stesso tipo di quella di partenza - si possono ottenere più segmenti per una linea, più triangoli per una patch triangolare, o più isolinee o quadrilateri per una patch quadrata, ma si ottiene sempre la stessa geometria. Il tessellation shader andrebbe usato quando c'è bisogno di generare molti nuovi vertici e una delle topologie di tassellatura soddisfa la necessità, o quando un richiesto input di una patch coinvolge molti (più di sei) vertici. Dall'altra parte, un geometry shader fornisce maggiori e differenti opportunità. Un geometry shader va usato quando c'è bisogno di convertire una topologia a una geometria differente, o se c'è bisogno di una qualche elaborazione geometrica dopo il tessellation shader.

Infine, il fatto che i geometry shader seguono i tessellation shader nella pipeline, crea una limitazione nell'utilizzo di questi ultimi. Un tessellation shader può solo generare segmenti di linea o triangoli; non può generare alcuna geometria con adiacenza. Se c'è bisogno di creare nuova geometria in un geometry shader e questa geometria richiede adiacenza, il geometry shader non può seguire il tessellation shader nella pipeline, e così non si può usare quest'ultimo.

### Geometry Shader

Il geometry shader rappresentò una nuova opportunità nell'ambito degli shader, quando fu introdotto nel tardo 2006 con il rilascio dello Shader Model 4 per ottenere vantaggio sulle sempre crescenti capacità delle schede grafiche di fascia alta. Esso allarga le abilità grafiche del programmatore fornendo strumenti per espandere la geometria basica del modello, attraverso l'inclusione di un maggiori numero o diverso tipo di primitive grafiche, oltre a quelle inizialmente definite.

Se si sta utilizzando un geometry shader, l'applicazione o il vertex shader possono generare tutti i tipi familiari di topologie:

* Punti
* Linee
* Line strips
* Line loops
* Linee con adiacenza
* Line strips con adiacenza
* Triangoli
* Triangle strips
* Triangle fans
* Triangoli con adiacenza
* Triangle strips con adiacenza
* Quadrilateri
* Quad strips

Tutte queste topologie possono essere utilizzate dall'applicazione, ma i geometry shader hanno un numero limitato di topologie che possono accettare. Queste sono punti, linee, linee con adiacenza, triangoli, o triangoli con adiacenza.

Nel caso dei vertex shader, la gestione di un solo vertice per volta rende difficile il calcolo delle normali basato su prodotti vettoriali degli spigoli. Lavorando con i geometry shader, vogliamo ancora usare le normali calcolate dalla geometria originale, poiché contengono un'informazione migliore, rispetto alle normali calcolate dai prodotti vettoriali degli spigoli. Comunque, i geometry shader danno accesso a tutte le informazioni di tutti i vertici di un triangolo o triangolo con adiacenza (in input), e questo può permetterci di calcolare le normali da prodotto vettoriale. Infatti, può essere sufficiente aggiungere un geometry shader a un'applicazione che usa un vertex o tessellation shader, ma che non supporta normali analitiche, semplicemente per essere in grado di calcolare le normali da prodotto vettoriale, per l'illuminazione.

### Fragment Shader

L'ultima fase in ambiente shader è il fragment processing, eseguita dal fragment shader o pixel shader. Questo prende le informazioni sviluppate dal vertex processing (vertex shader, tessellation shader, o geometry shader) ed espande le tradizionali operazioni di frammentazione permettendo di operare su ogni frammento individualmente per generare il colore del proprio pixel. Questa è un'operazione altamente parallela che può applicare texture tradizionali o procedurali; colorazione speciale, come le funzioni di trasferimento di pseudocolore; e tipi avanzati di shading, come il Phong o l'anisotropic shading. Il fragment shader ha l'impatto maggiore sull'effetto visivo dell'immagine.

La funzione basilare di un fragment shader è di prendere le uniform variables e l'output dal rasterizer e calcolare il colore del pixel per ogni frammento. Ovviamente, molte altre proprietà built-in dei vertici, nonché il colore e l'intensità luminosa, possono essere interpolate nel fragment processing. Le più importanti fra queste, sono le coordinate delle texture e la profondità dei pixel. Se si sta texturizzando, poiché le coordinate delle texture sono interpolate, si possono usare le coordinate per campionare una texture (o texture multiple), per aiutare a determinare il colore di ogni pixel.

L'uso dei pixel shader consente di applicare effetti come bump mapping, ombre, esplosioni, effetti di diffrazione, rifrazione e la simulazione dell'effetto fresnel (implementato nel videogioco Half-Life 2) permettendo una migliore simulazione degli effetti dell'illuminazione e un aspetto più realistico di superfici dalle proprietà ottiche particolari (come per esempio, effetti di rifrazione nei liquidi).

## Illuminazione

Il modo più semplice per rendere l'illuminazione è farlo attraverso il calcolo per-vertex, che porrebbe la responsabilità per la maggior parte del lavoro sulle spalle del vertex shader. Se l'illuminazione è resa in questo modo, il colore viene calcolato basandosi sulle proprietà della luce e del materiale - che determinano il colore di ogni vertice - basate sul modello standard di illuminazione ambient-diffuse-specular (ADS). Questo calcolo per-vertex può essere usato sia per il flat shading che per lo smooth shading. Tuttavia, se viene usato un modello di shading più complesso, come il Phong o l'anisotropic shading, la computazione del colore sarà probabilmente rinviata al fragment shader, dove può essere eseguito il calcolo per-pixel del colore.

Consideriamo, per semplicità, gli shader presenti in Blender.

### Diffuse Shader

Le immagini mostrano il diffuse shader con abbinato ogni specular shader (trattato in seguito) implementato nel programma Blender.

* Lambert e Minnaert shader in Blender
* Oren-Nayar shader in Blender
* Toon shader in Blender
* Esempio di applicazione del Toon shader
* Fresnel shader in Blender

**Lambert**

Si tratta dello shader di default. Non è dotato di particolari proprietà e permette di ottenere una morbida degradazione da punti luce a punti ombra.

**Oren-Nayar**

Questo shader permette di riprodurre in modo migliore le microscopiche irregolarità presenti sulla superficie di quasi ogni materiale. Legato al modello di riflessione sviluppato nei primi anni '90 da Michael Oren e Shree K. Nayar, è una generalizzazione della legge di Lambert oggi ampiamente utilizzata in computer grafica.

**Toon**

Toon appartiene alla categoria degli shader fisicamente non accurati. Il suo scopo è quello di fornire un risultato simile a quello delle illustrazioni bidimensionali colorate a campitura dei fumetti. Le aree di luce saranno pertanto molto omogenee e ben distinte dalle altrettanto omogenee aree di ombra.

**Minnaert**

Questo shader consiste sostanzialmente in una reimplementazione dello shader Lambert. Marcel Minnaert (1893-1970), è stato un astronomo belga che si è interessato degli effetti dell'atmosfera sulla luce e le immagini, che nel 1954 pubblicò un libro intitolato "The Nature of Light and Color in the Open Air".

**Fresnel**

Nel calcolo della diffusione, uno shader Fresnel non tiene in considerazione soltanto l'angolo che si crea tra il piano del punto di vista e la superficie illuminata dell'oggetto, ma aggiunge ai calcoli anche l'angolo di incidenza della luce sulla superficie dell'oggetto. In particolare, più parallelamente giungeranno i raggi rispetto alla normale di una superficie, minore sarà la diffusione; al contrario, più perpendicolari saranno i raggi, maggiore sarà la diffusione.

### Specular Shader

È necessario non farsi ingannare dal termine Specular, il quale non è per nulla riferito al fenomeno di riflessione caratteristico degli specchi, bensì riguarda il noto fenomeno della formazione di un punto di massima luminosità (o alta luce, o punto luce, questo è il termine corretto in italiano, in riferimento a specular highlight) su una qualsiasi superficie in grado di riflettere la luce. Spesso questi due fenomeni non sono facilmente distinguibili, tuttavia è possibile impiegare il seguente metodo per avere le idee più chiare: più la superficie del materiale sarà liscia, regolare e priva di imperfezioni, più sarà visibile la riflessione delle alte luci. Per esempio, una palla da biliardo è talmente liscia da creare anche un effetto di riflessione speculare; d'altro canto, più la superficie sarà ruvida e irregolare, più prevarrà la riflessione diffusa. È possibile creare svariati abbinamenti fra shader Diffuse (dentro le parentesi) e Specular. L'immagine sotto ne propone alcuni e contemporaneamente illustra l'effetto di ogni Specular Shader.

**CookToor**

Il nome esteso di questo shader è Cook-Torrance e lo si può considerare una versione evoluta dello shader Phong. Si adatta particolarmente alla resa di superfici organiche o inorganiche piuttosto lisce, come la plastica e il cuoio. Robert L. Cook (LucasFilm) e Kenneth E. Torrance (Cornell University) nel proprio documento del 1982 "A Reflectance Model for Computer Graphics", descrissero "un nuovo modello di riflessione per renderizzare immagini sintetizzate al computer" e lo applicarono per la simulazione di metalli e plastica.

**Phong**

Phong è uno dei primi metodi di shading messi a punto nella storia della computer grafica. Si tratta di uno shader estremamente semplice, che si adatta bene alla resa di materiali metallici.

**Blinn**

Blinn aggiunge un controllo IOR (Index Of Refraction, indice di rifrazione), permettendo un maggiore realismo. Nel caso di Blinn il punto di riflessione delle alte luci può avere un diametro molto più ridotto rispetto a Phong e CookToor. È spesso usato con il diffuse shader Oren-Nayar. Il modello è stato descritto da Jim Blinn nel 1977.

**Toon**

Questo shader viene solitamente coordinato con il diffuse Toon. È in grado di produrre (in modo simile al diffuse) un punto luminoso estremamente definito.

**WardIso**

Quest'ultimo shader risulta utile nella creazione di materiali plastici o metallici. Gregory J. Ward sviluppò un modello relativamente semplice che obbedisce alle leggi più basilari della fisica. Nella sua pubblicazione del 1992, "Meauring and modeling anisotropic reaction", Ward introdusse una Bidirectional Reflectance Distribution Function (BRDF), da allora utilizzata ampiamente nella computer grafica perché i pochi parametri che considera sono semplici da controllare. Il suo modello può rappresentare sia le superfici isotropiche (indipendenti dalla direzione della luce), sia le superfici anisotropiche (dipendenti dalla direzione della luce). In Blender lo specular shader Ward è ancora chiamato "Ward Isotropic", ma è in realtà anisotropico.

