Quando l'illuminazione e' disabilitata, ogni vertice ha il suo colore (assegnato con glColor), e ogni punto facente parte di una primitiva 1D (GL_LINES,...) o 2D (GL_TRIANGLES, GL_POLYGON,...) ha un colore ottenuto interpolando quello dei vertici della primitiva.
Ne segue che una primitiva ha un unico colore uniforme se i suoi vertici hanno tutti lo stesso colore. Quindi in 3D se tutte le facce di un solido hanno stesso colore, il solido appare come un'unica macchia di colore senza effetto di tridimensionalita'.
L'illuminazione si abilita con glEnable(GL_LIGHTING).
Quando l'illuminazione e' abilitata, ogni punto viene colorato con:
Fattori che entrano in gioco per colorare una primitiva:
Luce ambiente:
Non proviene da una direzione particolare, non viene riflessa in
una direzione particolare.
Colpisce con la stessa intensita' ogni punto indipendentemente
dall'inclinazione della superficie a cui il punto appartiene.
L'osservatore percepisce la stessa intensita' di colore
indipendentemente da dove si trova.
Attribuisce a un oggetto formato da facce con inclinazioni diverse
un unico colore UNIFORME.
L'oggetto appare come un'unica macchia di colore senza effetto 3D.
Luce diffusa:
Proviene da una direzione in particolare, non viene riflessa in
una direzione particolare.
Colpisce ogni punto con intensita' che dipende dall'angolo
formato dalla direzione della luce incidente
con la normale alla superficie in quel punto.
L'osservatore percepisce la stessa intensita' di colore
indipendentemente dalla sua posizione.
Facce con inclinazioni diverse
riflettono la luce con intensita' diversa.
Ogni faccia viene appare di colore piu' o meno intenso secondo
la sua inclinazione, creando EFFETTO 3D.
Luce speculare:
Proviene da una direzione in particolare,
viene riflessa in una direzione in particolare.
L'intensita' con cui l'osservatore vede illuminato un punto
dipende dalla posizione dell'osservatore.
Crea effetto di LUCCICHIO, tipo i metalli.
Ogni sorgente luminosa contiene queste tre componenti di luce, e ciascuna componente puo' avere colore e intensita' diversa. Inoltre esiste una luce ambiente "di sfondo", indipendente dalle sorgenti luminose (attiva anche a sorgenti luminose spente).
Ogni materiale ha una sensibilita' particolare a ciascuna delle tre componenti della luce. Inoltre esistono materiali in grado di emettere luce propria (luce emessa).
Posso definire una o piu' sorgenti luminose e, dopo averle definite, abilitarle/disabilitarle (per default disabilitate).
Ogni sorgente e' caratterizzata da
Si considerano sorgenti puntiformi. In base alla collocazione distinguiamo tre tipi di sorgenti:
La posizione della luce e' soggetta alle trasformazioni come tutte le primitive geometriche, in particolare e' soggetta alla matrice modelview corrente.
Ogni sorgente luminosa emette tutti e tre i tipi di luce (ambiente, diffusa, speculare). Ciascun tipo ha un certo colore e intensita'.
La luce emessa da una sorgente e' descritta da una terna RGB per
ogni tipo di luce.
Il colore e' dato dalla proporzione fra rosso, verde, blu.
L'intensita' e' data dal valore assoluto.
Se un tipo di luce non e' emesso, la terna e' (0,0,0) = luce nera.
Definizione della sorgente: glLight(luce, nome_parametro, valore_parametro);
La funzione ha 4 varianti glLightf glLighti, glLightfv, glLightiv
luce = GL_LIGHT0, GL_LIGHT1,... (OpenGL fornisce almento 7 luci)
nome_parametro e valore sono illustrati dalla seguente tabella:
nome | valore (scalare o vettore) |
GL_AMBIENT | vettore di componenti RGBA, default (0,0,0,1), luce ambiente emessa dalla sorgente |
GL_DIFFUSE | vettore di componenti RGBA, default (1,1,1,1) per GL_LIGHT0 e (0,0,0,1) per le altre, luce diffusa emessa dalla sorgente |
GL_SPECULAR | vettore di componenti RGBA, default (1,1,1,1) per GL_LIGHT0 e (0,0,0,1) per le altre, luce speculare emessa dalla sorgente |
GL_POSITION | vettore di coordinate (x,y,z,w) posizione della luce, w=1 per posizione in un punto (x,y,z) al finito, w=0 per posizione all'infinito nella direzione del vettore (x,y,z) |
...altri parametri per le luci spot (di cui non ci occupiamo)... | |
...altri parametri per specificare come la luce e' attenuata con l'aumentare della distanza dalla sorgente (non ce ne occupiamo)... |
Abilitazione della sorgente: glEnable(luce);
dove luce = GL_LIGHT0, GL_LIGHT1,...
Il modello di illuminazione controlla
glLightModel(nome_parametro, valore_ parametro)
Anche questa funzione ha 4 versioni: glLightModelf, glLightModeli, glLightModelfv, glLightModeliv.
nome_parametro e valore sono illustrati dalla seguente tabella:
nome | valore (scalare o vettore) |
GL_LIGHT_MODEL_AMBIENT | vettore di componenti RGBA della luce ambiente "di sfondo" (default 0.2,0.2,0.2,1) |
GL_LIGHT_MODEL_TWO_SIDE | 0 oppure 1 (default = 0), 0 = illumina solo front faces (in oggetti "chiusi" le back faces non si vedono...) |
GL_LIGHT_MODEL_LOCAL_VIEWER | 0 oppure 1 (default = 0), 0 = non tiene conto della posizione del punto di vista nel calcolo delle riflessioni speculari (meno accurato ma piu' veloce) |
Il materiale e' un attributo presente nello stato del sistema che influenza le primitive.
Il materiale stabilisce, per le primitive immediatamente seguenti:
Un materiale e' descritto da una terna RGB per ciascun tipo di luce,
e una terna RGB per la luce emessa.
Se un tipo di luce non e' riflesso dal materiale,
la terna e' (0,0,0) = nessuna riflessione.
Se il materiale non emette luce propria, la luce emessa e' (0,0,0) =
luce nera.
Il materiale corrente e' assegnato con
glMaterial(faccia, nome_parametro, valore_parametro);
La funzione ha 4 varianti: glMaterialf, glMateriali, glMaterialfv, glMaterialiv, dove
faccia = GL_FRONT, GL_BACK o GL_FRONT_AND_BACK per assegnare proprieta' alle front faces, le back faces, o a entrambe
nome_parametro e valore sono illustrati dalla seguente tabella:
nome | valore (scalare o vettore) | |
GL_AMBIENT | vettore di componenti RGBA, default (0.2,0.2,0.2,1), frazione di luce ambiente ricevuta che la primitiva riflette, per ogni colore | |
GL_DIFFUSE | vettore di componenti RGBA, default (0.8,0.8,0.8,1), frazione di luce diffusa ricevuta che la primitiva riflette, per ogni colore | |
GL_SPECULAR | vettore di componenti RGBA, default (0,0,0,1), frazione di luce speculare ricevuta che la primitiva riflette, per ogni colore | |
GL_AMBIENT_AND_DIFFUSE | per assegnare contemporaneamente GL_AMBIENT e GL_DIFFUSE con lo stesso vettore RGBA | |
GL_EMISSION | vettore di componenti RGBA, default (0,0,0,1), componenti della luce emessa dalla primitiva stessa | |
GL_SHININESS | intero tra 0 e 128, intensita' della luce speculare riflessa |
Nel caso di luce diffusa, l'intensita' dell'illuminazione dipende dall'angolo
formato dalla direzione della luce con la normale alla superficie.
OpenGL NON calcola da solo le normali, bisogna fornirgliele.
La normale e' un attributo presente nello stato del sistema che influenza i verttici delle primitive.
glNormal3f(tre float) oppure glNormal3fv(vettore di tre float)
Varie forme analogamente a quanto visto per glVertex...
Puo' essere chiamata tra glBegin e glEnd.
Influisce tutti i vertici che
seguono fino a che la normale corrente non viene modificata di nuovo.
Tipicamente:
In realta' la normale e' uno di quegli attributi OpenGL che valgono "vertice per vertice" (come anche il colore). Posso assegnare una normale diversa a ogni vertice della stessa faccia. La normale per ciascun punto interno della faccia e' allora interpolata, cosicche' la normale cambia gradualmente all'interno della faccia.
Per default la normale corrente e' (0,0,0) e gli oggetti appaiono "piatti" (colorati di colore uniforme anche in presenza di luce diffusa, nonostante l'inclinazione diversa delle facce).
Anche le normali, come le coordinate dei
vertici, sono "geometria", e subiscono le trasformazioni geometriche.
Se una primitiva viene sottoposta a trasformazioni di scalatura,
le normali possono risultare non piu' "normali" dopo la trasformazione.
L'istruzione glEnable(GL_NORMALIZE); abilita la normalizzazione automatica delle normali.
Risolve il problema citato sopra e inoltre consente di passare a glNormal vettori di norma non necessariamente = 1.
Reazione alla luce ambiente: si moltiplicano componente per componente la terna RGB della luce ambiente e la terna RGB della reazione del materiale alla luce ambiente.
Reazione alla luce diffusa: si procede nello stesso modo che per la luce ambiente ma il risultato si moltiplica per il coseno dell'angolo formato dalla direzione della luce incidente con la normale alla primitiva (=1 se la luce incide perpendicolarmente, 0 se e' radente).
Reazione alla luce speculare: come per la luce diffusa ma alla luce riflessa e' attribuita una direzione di riflessione e si moltiplica anche per il coseno dell'angolo formato dalla luce riflessa con la direzione dello sguardo dell'osservatore.
Le reazioni ai tre tipi di luci si sommano fra loro e si sommano alla luce emessa.
Per ottenere una scena illuminata bisogna:
In presenza di luci, il colore apparente di un oggetto e' determinato dal colore della luce che riflette, e apparentemente glColor non ha effetto.
Si puo' usare l'istruzione glColorMaterial per far si' che i parametri di materiale seguano il valore attuale del colore assegnato con glColor.