Inserisci Infobox

OpenGL Overview

Texture Mapping
Autore: HTC - Ultimo Aggiornamento: 2003-11-16 19:31:33 - Data di creazione: 2003-11-16 19:31:33
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

Il texture mapping è una tecnica molto utilizzata nel campo del rendering poichè è in grado elevare notevolmente il realismo della scena.

Sostanzialmente consiste nell'incollare un'immagine ad un oggetto composto da uno o più poligoni. Per esempio, supponendo di avere dei poligoni che rappesentino un muro e un'immagine che rappresenta dei mattoni possiamo applicare l'immagine ai poligoni ottenendo così l'effetto di un vero e proprio muro di mattoni. Inoltre, dato che il costo per la manipolazione dell'immagine non dipende da ciò che è rappresentato ma dalla risoluzione, possiamo utilizzare immagini ricche di particolari, infatti è ormai pratica comune utilizzare direttamente (o dopo piccoli ritocchi) le foto di una camera digitale.
Quando vogliamo texturizzare un oggetto dobbiamo creare creare una texture partendo dall'immagine che vogliamo applicare. La texture è un tipo di dato particolare che solitamente viene gestito direttamente dalla libreria grafica di basso livello (OpenGL) perchè bisogna eseguire diverse operazioni per adattare l'immagine all'oggetto.
Solitamente un'immagine viene visualizzata come un rettangolo la cui altezza e lunghezza dipendono dal numero di pixel impiegati, ma quando viene applicata a un poligono deve assumere la forma e la dimensione di quest'ultimo. Ciò significa che se il nostro oggetto è molto grande la nostra immagine dovrà essere "tirata", se invece il nostro oggetto è piccolo o lontano l'immagine sarà molto ridotta. Inoltre è necessario che durante le trasformazioni geometriche dell'oggetto (rotazioni etc.) l'immagine sia sempre visualizzata in modo corretto.

In OpenGL il Texture Mapping è validamente supportato, peraltro oltre al Texture Mapping tradizionale con immagini 2D è disponibile sia il mapping con texture 1D (cioè immagini con altezza uguale a 1) sia con texture 3D. Le Texture 3D (immagini che hanno una profondità) si possono utilizzare per realizzare effetti interessanti, ma esigono una grande quantità di memoria e sono attualmente poco usate.
  
Per abilitare o disabilitare un determinato tipo di Texture Mapping si utilizzano i parametri:
  - GL_TEXTURE_2D Le normali texture 2D
  - GL_TEXTURE_1D Le texture 1D
  - GL_TEXTURE_3D Le texture 3D

I passi da seguire per creare una texture sono i seguenti:
  - Generazione di un riferimento alla texture
  - Attivazione del riferimento
  - Settaggio dei parametri
  - Creazione della Texture mediante l'immagine  

Generazione di un riferimento alla texture
Si tratta di indicare ad OpenGL che vogliamo riservare spazio per una o più texture che utilizzeremo successivamente.
Per distinguere univocamente le diverse texture per ogni riferimento creato viene restituito un numero intero.
La funzione da utilizzare è:
void glGenTextures(GLsizei n, GLuint *textureNames);
n è il numero di Texture che vogliamo creare, textureNames è l'indirizzo di un intero o di un array di interi dove saranno memorizzati gli identificativi per ogni texture creata.

Attivazione del riferimento
Questa operazione consiste nel rendere attuale, cioè attiva, una delle texture create. OpenGL infatti in ogni momento può lavorare su una sola texture.
Per tale compito usiamo la funzione:
void glBindTexture(GLenum target, GLuint textureName);
target è quale tipo di texture attivare, textureName è l'identificativo della texture che abbiamo ottenuto con la chiamata a glGenTextures.

Settaggio dei parametri
Questa fase è più complicata poichè si devono impostare i parametri che andranno a influire sulla rappresentazione della texture.
I parametri più importanti che si devono modificare sono i filtri e precisamente il Magnification filter e il Minification filter.

Il Magnification filter entra in azione quando un pixel reale rappresenta solo una piccola parte di una texel, cioè di un pixel della texture. Questo succede quando la nostra texture è molto piccola e viene applicata su un oggetto molto grande, oppure quando l'oggetto è molto vicino alla vista dell'utente. Un esempio lampante dell'azione di un filtro di questo genere è quando in giochi FPS come Quake ci avviciniamo al muro, in questi casi il software tenta di nascondere l'immagine "pixellosa" attraverso una serie di interpolazioni.

Per modificare dei parametri della texture utilizziamo la funzione:
void glTexParameter{if}(GLenum target, GLenum pname, TYPE param);
target è il tipo di texture, pname è il parametro che vogliamo modificare, param e' il valore che assumera' il parametro.

In particolare per modificare il Magnification filter pname sarà uguale a GL_TEXTURE_MAG_FILTER e param indicherà il tipo di filtro da utilizzare.
Sono disponibili i seguenti filtri:
- GL_NEAREST Utilizza la texel più vicina al pixel che deve essere texturizzato
- GL_LINEAR Interpolazione lineare delle 4 texels più vicine al pixel che deve essere texturizzato
Naturalmente GL_NEAREST sarà più veloce mentre GL_LINEAR darà risultati migliori.

Il Minification filter è invece esattamente il contrario del Magnification, viene utilizzato quando la texture è più grande dell'oggetto su cui viene incollata o quando l'oggetto è lontano, quindi significa che una texel rappresenta più pixel reali.
Si utilizza la stessa funzione con pname uguale GL_TEXTURE_MIN_FILTER e sono a disposizione i medesimi parametri. Per il Minification filter si possono però utilizzare altre opzioni grazie alla tecnica del mipmapping che vedremo più tardi.

Altri settaggi importanti che in OpenGL vanno sotto il nome di Texture Functions sono il modo in cui i colori delle texture influiscono sugli oggetti. Si utilizza:
void glTexEnv{if}(GLenum target, GLenum pname, TYPE param);
target deve essere uguale a GL_TEXTURE_ENV, pname sarà uguale a GL_TEXTURE_ENV_MODE mentre param può assumere uno dei seguenti valori:
- GL_BLEND Il Colore della texture viene moltiplicato per il colore del pixel e infine moltiplicato per una costante.
- GL_DECAL Il Colore della texture sostituisce quello del colore
- GL_MODULATE Il colore della Texture viene moltiplicato per quello del pixel.

Creazione della Texture
Infine possiamo indicare ad OpenGL quale immagine vogliamo utilizzare per creare la nostra texture. La funzione per eseguire tale compito è:
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum             format, GLenum type, const GLvoid *pixels);
target deve essere uguale a GL_TEXTURE_2D;
level indica se ci sono risoluzioni multiple (in caso negativo sarà uguale a 0);
internalFormat descrive il formato delle Texels (GL_RGB>, GL_RGBA, ma anche GL_LUMINACE, GL_LUMINANCE_ALPHA);
width e height sono la dimensione dell'immagine;
border indica se vogliamo che la texture abbia un bordo;
format indica il formato dati dell'immagine (GL_RGB, GL_RGBA...)
type indica il tipo di dato utilizzato (GL_UNSIGNED_BYTE, GL_SHORT...)
pixels (o texels) è il puntatore ai dati dell'immagine;

Rappresentazione delle Texture
Una volta creata la texture per utilizzarla dobbiamo attivarla e indicare le sue coordinate rispetto al poligono.
Per attivarla chiamiamo di nuovo glBindTexture passandogli l'identificativo.
Vengono utilizzate le coordinate (s,t) dove s indica il valore in x e t il valore in y all'interno dell'immagine. Ad ogni vertice del poligono che vogliamo texturizzare dobbiamo associare una coppia di coordinate s,t.
Per esempio in un quadrato definito dalle coordinate:
Vertice in basso a sinistra: -1.0, -1.0;
Vertice in basso a destra  : 1.0, -1.0;
Vertice in alto a destra   : 1.0, 1.0;
Vertice in alto a sinistra : -1.0, 1.0;

Le coordinate delle texture saranno:
Vertice in basso a sinistra: 0.0, 0.0;    
Vertice in basso a destra: 1.0, 0.0;
Vertice in alto a destra: 1.0, 1.0;
Vertice in alto a sinistra: 0.0, 1.0;

-- Possibile Inserimento Immagine --

La funzione per indicare le coordinate è semplicemente:
void glTexCoord2{if}(TYPE coords);
Il codice per l'esempio del quadrato dimostra come prima del vertice devono essere specificate le coordinate texture associate.
glBegin(GL_QUADS); // Disegnamo un quadrato
  glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);  
  glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
  glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
  glTexCoord2f(-1.0, 1.0); glVertex3f(-1.0, 1.0, 0.0);
glEnd();        // Fine Disegno    


Repeating e Clamping
Può essere utile ripetere una determinata texture più volte all'interno dello stesso oggetto. Riprendendo l'esempio del muro di mattoni è probabile che il nostro muro sia molto grande e che la texture sia piuttosto piccola. Applicando semplicemente la texture al muro questa verrà "tirata". Per evitare questo problema possiamo settare il repeating della texture e indicare coordinate maggiori di 1.0.

Possiamo ottenere questo effetto attraverso glTexParameter, con pname uguale a GL_TEXTURE_WRAP_S per la coordinata s e GL_TEXTURE_WRAP_T per la coordinata t, indicando come param GL_REPEAT.
A questo punto quando la texture verrà visualizzata con coordinata finale (2.0, 2.0), vedremo che la texture è stata riprodotta 4 volte.
Settando invece il param a GL_CLAMP è possibile riempire solamente 1/4 dell'oggetto.

Clean Up
Per eliminare una texture si chiama semplicemente la funzione
void glDeleteTextures(GLsizei n, const GLuint *textureNames);
n è il numero di texture che vogliamo eliminare e textureNames è l'indirizzo degli identificativi delle texture da eliminare.

Mipmapping
Per migliorare la qualità di visualizzazione delle texture quando queste si presentano più piccole è possibile creare un certo numero di texture con la stessa immagine ma con dimensioni differenti, in questo modo a seconda della dimensione del poligono al quale deve essere applicata OpenGL utilizzerà la texture più adatta.
Questa operazione può essere fatta o attraverso chiamate multiple a glTexImage settando il parametro level con valori crescenti, oppure utilizzando una funzione di utilità della libreria glu:
int gluBuild2DMipmaps(GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, void *data);
target è il tipo di texture da create GL_TEXTURE_2D
components corrisponde all'internal format di glTexImage
width e height sono le dimensioni dell'immagine iniziale
format è il tipo di formato dati dell'immagine
type è il tipo di dato in cui sono contenuti i valori

Questa funzione costruirà automaticamente una serie di texture più piccole partendo da quella originale.
Se utilizziamo le mipmaps quando settiamo i parametri per il Minification filter dobbiamo utilizzare uno di questi valori:
- GL_NEAREST_MIPMAP_NEAREST usa la texture più vicina alla risoluzione del poligono e il filtro GL_NEAREST
- GL_NEAREST_MIPMAP_LINEAR usa la texture più vicina alla risoluzione del poligono e il filtro GL_LINEAR
- GL_LINEAR_MIPMAP_NEAREST usa interpolazione tra le 2 texture vicine alla risoluzione del poligono e il filtro GL_NEAREST
- GL_LINEAR_MIPMAP_LINEAR usa interpolazione tra le 2 texture vicine alla risoluzione del poligono e il filtro GL_LINEAR

OpenGL, una macchina a stati
Autore: HTC - Ultimo Aggiornamento: 2004-03-31 22:16:59 - Data di creazione: 2004-03-31 22:16:59
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

OpenGL è considerata una macchina a stati in quanto le operazioni da lei eseguite nel processare dati geometrici e pixel sono guidate dallo stato in cui si trovano i parametri interni, variando i parametri si ottengono risultati differenti.

I valori dei parametri sono accessibili attraverso delle funzioni create appositamente per questo scopo ed è quindi possibile cambiare lo stato della macchina in ogni punto del codice. Questo significa che durante le operazioni di disegno si può abilitare e disabilitare più volte una determinata capacità.
Ognuno di questo stati, sono diverse decine, entra in gioco in una o piu' fasi della rendering pipeline durante la quale viene coinvolto ogni aspetto della renderizzazione, dal tipo di primitiva di disegno, al colore, all'intensità della luce, ai filtri delle texture.

Le funzioni che OpenGL offre per acquisire i parametri sono le seguenti:
void glGetBooleanv(GLenum pname, GLboolean *params);
void glGetDoublev(GLenum pname, GLdouble *params);
void glGetFloatv(GLenum pname, GLfloat *params);
void glGetIntegerv(GLenum pname, GLint *params);

pname è il parametro di cui vogliamo sapere il valore mentre params è il puntatore alla zona di memoria dove verranno inseriti i dati di ritorno.

Ad esempio il codice seguente acquisisce nella variabile color il colore attuale:
float *color = new float[4];
glGetFloatv(GL_CURRENT_COLOR, color);

Un'ulteriore funzione molto semplice per controllare se una determinata modalità è attiva è :
GLboolean glIsEnabled(GLenum cap);
dove enum è la modalità da controllare.

Mentre le funzioni per l'acquisizione fanno parte di una stessa famiglia glGet* non esiste una controparte glSet per impostare i diversi valori, ma si utilizzano invece delle funzioni il cui nome può variare in base al parametro di cui si occupano.
Una funzione usata per un gran numero di operazioni che riguardano l'attivazione o la disattivazione di un parametro è :
void glEnable(GLenum cap);
e la sua inversa
void glDisable(GLenum cap);
dove cap è lo stato da modificare.

Un esempio di utilizzo:
if(glIsEnabled(GL_BLEND))
glDisable(GL_BLEND);
    
Altri parametri, come accennato, hanno funzioni apposite. Ne è un esempio la famiglia di funzioni glColor* per la gestione del colore e la famiglia di funzioni glLight* per la gestione delle fonti di luce.
Questo codice imposta bianco il GL_CURRENT_COLOR  
glColor3f(1.0, 1.0, 1.0);
Può rendersi necessario variare temporaneamente il valore di alcuni parametri per poi riportarli nella situazione iniziale, a questo scopo sono presenti le due funzioni glPushAttrib e glPopAttrib.
void glPushAttrib(GLbitfield mask);
void glPopAttrib(void);

La prima salva in uno stack i valori interessati dalla maschera di bit mask mentre la seconda ripristina il valori precedentemente salvati.

OpenGL Rendering Pipeline
Autore: HTC - Ultimo Aggiornamento: 2004-04-01 09:44:49 - Data di creazione: 2004-04-01 09:44:49
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

La rendering pipeline è il percorso che devono seguire i dati grezzi forniti dal programma client prima di essere visualizzati sullo schermo.

Durante questo percorso le informazioni vengono elaborate, trasformate e combinate in base ai valori dei parametri interni di OpenGL.  
I dati in input sono principalmente di due tipi:
- Coordinate spaziali, cioè vertici e punti
- Immagini, pixels e bitmap



Inizialmente questi due tipi di informazioni seguono un percorso differente ma infine vengono combinati per formare l'immagine, memorizzata nel framebuffer, che sarà poi visualizzata.
L'operazione Display List che si vede tra i due flussi principali non è obbligatoria e non influisce sulla visualizzazione dell'immagine bensì sulle prestazioni. Grazie alle Display List, infatti, si possono salvare una serie di valori pre-elaborati in modo da saltare alcuni passi della pipeline e velocizzare il lavoro.

Seguendo il percorso dei Vertex Data notiamo che passano per Evaluators, in questo nodo vengono eseguite delle operazioni solo su gli oggetti definiti come curve quali Bezier curve e NURBS. Le curve sono descritte da alcuni Control points sui i quali vengono eseguite calcoli di derivazione per trovare i vari vertici che le compongono.
Il passo successivo (Per-Vertex Operation) è senza dubbio quello più pesante dal punto di vista delle operazioni, infatti qui le coordinate di tutti i vertex vengono sottoposte alle matrici di trasformazione che hanno il compito di eseguire traslazioni, rotazioni e ridimensionamenti. Oltre alle coordinate dei vertici si devono calcolare le posizioni delle texture e gli effetti derivanti dall'illuminazione.
Nel passo successivo, Primitive Assembly, viene eseguito il clipping dei poligoni nascosti, il calcolo delle profondità ed si eseguono le operazioni relative alla proiezione in prospettiva (se attivata).

Per quanto riguarda il percorso delle immagini innanzitutto vengono attivate le procedure di unpacking dai vari buffer di memoria indicati dal programma client, poi le immagini vengono ruotate, ridimensionate e passate alla texture assembly o direttamente alla fase di rasterization. Nella texture assembly si presta particolare attenzione ai calcoli per il texture mapping.

Infine i due flussi si combinano nel processo detto di rasterization e sia i vertici sia le immagini vengono trasformati in fragments, ognuno dei quali rappresenta un pixel del framebuffer. Qui vengono riempiti i poligoni ed eseguite le operazioni di antialiasing, ad ogni fragments viene associato un colore e una profondità.
Prima che i fragments vengano scritti sul framebuffer viene eseguita su di essi la copia dei pixel delle texture, che in base ai parametri adottati possono sovrascrivere o modificare i colori dei poligoni, ed inoltre vengono eseguiti i test in base ai parametri di trasparenza e in base ai valori contenuti nello stencil buffer e nel depth buffer.

Quando, dopo tutte le operazioni di disegno, il framebuffer è finalmente completo esso viene copiato nella memoria video e verrà visualizzato sullo schermo.      

Teoria di base dell'illuminazione
Autore: HTC - Ultimo Aggiornamento: 2003-11-27 17:41:26 - Data di creazione: 2003-11-27 17:41:26
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

La possibilità di aggiungere illuminazione alla nostra scena è senza dubbio una prospettiva interessante e alza notevolmente il livello di realismo della scena stessa, è necessario comprendere la teoria che ne sta alla base per poterla sfruttare al meglio.

La luce e'un elemento fondamentale per rappresentare la realtà, infatti guardandoci intorno possiamo notare che tutti gli oggetti vengono in qualche modo influenzati da essa.
La luce è considerata in fisica come una serie di onde elettromagnetiche (percepibili dai nostri occhi) che viaggiano in linea retta. D'altraparte alcuni materiali, in maniera diversa, hanno la possibiltà di deviare la luce. Questo fenomeno, detto riflessione, è molto frequente e si ottiene ad esempio accendendo un lampadario all'interno di una stanza:
gran parte della luce che noi vediamo è quella che viene riflessa dai muri e non quella che effetivamente scaturisce dal lampadino.
I raggi di luce, riflessi e non, vanno a modificare i colori degli oggetti che vengono colpiti.
Il procedimento che viene utilizzato dal software per calcolare l'effetto dell'illuminazione su un oggetto si basa sull'angolo compreso tra il vettore della luce, cioè il vettore che parte dal poligono e punta verso la posizione della luce, e il vettore normale del poligono.
Il vettore normale è un vettore perpendicolare alla superficie del poligono ed èimportantissimo per una vasta gamma di operazioni. Se l'angolo compreso tra i due vettori è uguale a 0° significa che la luce colpisce perpendicolarmente il poligono il cui colore sarà schiarito, se, al contrario, l'angolo è maggiore di 90° allora il poligono non sara illuminato e il suo colore apparirà più scuro (un angolo di 90° gradi significa che i raggi sono paralleli alla superficie).

Calcolare il vettore normale
Il primo obiettivo è calcolare il vettore normale di ogni poligono che è dato dal prodotto vettoriale di due vettori appartenenti al esso. Supponendo di avere un triangolo con i vertici v1 v2 e v3 dobbiamo prima trovare i due vettori U, V appartenenti al triangolo e poi calcolarne il prodotto vettoriale.

Calcolo dei vettori:

U = v2 - v1;
V = v3 - v2;

Il prodotto vettoriale:

N = U x V;
N.x = U.y * V.z - U.z * V.y
N.y = U.z * V.x - U.x * V.z
N.z = U.x * V.y - U.y * V.x

Calcolare l'illuminazione
Il calcolo dell'illuminazione viene eseguita in modo efficiente da OpenGL ma è utile comprenderne il funzionamento. La formula che si utilizza per calcolare l'angolo, e quindi la quantità di luce su un determinato poligono, è la seguente:
        
cos(alfa) = L * N / |L| * |N|

L èil vettore della luce;
N èil vettore normale del poligono;
|L| e |N| sono i moduli (la forza) dei vettori;

Questa operazione deve essere eseguita per ogni faccia del poligono, è quindi necessario ottimizzarla.
Per migliorare notevolmente le prestazioni basta considerare L e N vettori unitari (di forza uno).
Il procedimento per rendere un vettore qualsiasi un vettore di forza unitaria prende il nome di normalizzazione.
Si calcola la forza del vettore

|N| = sqrt(N.x^2 + N.y^2 + N.z^2)

poi si dividono tutte le componenti del vettore per tale forza:

N.x = N.x / |N|  
N.y = N.y / |N|
N.z = N.z / |N|

Si ottiene in questo modo il vettore normalizzato.
La formula ora è meno complessa:

cos(alfa) = L * N

Il valore cos(alfa) viene utilizzato da OpenGL per decidere da quanta luce è colpito un determinato poligono e agire di conseguenza sul colore.    

Tecniche di illuminazione
Avendo calcolato il vettore normale per ogni poligono possiamo dar vita a una illuminazione detta Flat Shading, questo tipo di illuminazione seppur relativamente veloce ha il difetto di far apparire gli oggetti come sfaccettati, infatti il valore cos(alfa) risultato dal calcolo viene esteso in modo uniforme sull'intero poligono. In realtà questo non è vero perchè all'interno dello stesso poligono possono esserci diverse sfumature.
Una tecnica in grado di colmare queste lacune e il Goraud Shading, nel quale l'attenzione passa dal poligono ai vari vertici che lo compongono.
Per implementare il Goraud Shading dobbiamo specificare un vettore normale non più per ogni poligono bensì per ogni vertice del poligono. Si tratta quindi di un calcolo più oneroso. Al fine di elaborare correttamente un vettore normale per ogni vertice (anche se matematicamente calcolare il vettore normale di un vertice non ha senso) si esegue la media dei vettori normali di ogni poligono a cui quel vertice appartiene.

Nv = N1 + N2 + N3 + ... Nn / n

Nv è il vettore normale riferito al vertice
Ni sono i normali dei poligoni che hanno in comune il vertice
n è il numero di poligoni che hanno in comune il vertice
Il risultato ottenuto è senza dubbio migliore.

Specificare i vettori normali
Mentre OpenGL si occupa di gestire direzione, intensità e colori delle luci a noi tocca indicare i vettori normali. Dobbiamo ricordarci di normalizzare il vettore prima di passarlo ad OpenGL.
Le funzioni che dobbiamo utilizzare per indicare i normal vectors sono:

glNormal3{bsifd}(TYPEx, TYPEy, TYPEz);
glNormal3{bsifd}v(TYPEnv* vector);

Il seguente codice disegna un triangolo e indica il relativo normal vector.

glBegin(GL_TRIANGLES);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
  
Naturalmente i normal vectors vengono influenzati da tutte le operazioni di rotazione e traslazione applicate all'oggetto, e necessario però porre attenzione ad operazioni di scaling che potrebbero modificare la lunghezza del vettore. Prima di queste operazioni si deve attivare il parametro GL_NORMALIZE che indica ad OpenGL di provvedere a ri-normalizzare i normal vectors.

OpenGL Lighting
Autore: HTC - Ultimo Aggiornamento: 2003-11-27 17:40:33 - Data di creazione: 2003-11-27 17:40:33
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

La possibilità di modificare colore intensità e posizione della luce all'interno della scena permette di ricreare ogni tipo di illuminazione con un elevata fedeltà.

Il sistema di illuminazione di OpenGL mette a disposizione un numero limitato di fonti di luce che per la maggior parte delle implementazioni è uguale a 8, esse vengono identificate dall'etichetta GL_LIGHTi dove i è il numero della luce partendo da 0. Anche se apparentemente questo numero sembra piuttosto piccolo in realtà in pochissime circostanze avremo più di 8 luci all'interno della stessa scena, ciò è comprensibile anche solo per l'oneroso compito di eseguire le operazioni di calcolo dell'illuminazione per più di 8 volte.
Se nella scena sono comunque presenti più luci di quante rese disponibili dovremo decidere quali attivare e quali disattivare in base alla posizione dell'osservatore.

Le componenti della luce
OpenGL suddivide una fonte di luce in 3 componenti: Ambient, Diffuse e Specular.

Ambient Light
Viene considerata Ambient Light la luce di cui non si riesce ad identificare la direzione e di conseguenza nemmeno una sorgente ben precisa, si tratta dei raggi che sono stati riflessi talmente tante volte che ormai se ne è persa traccia ma che comuque illuminano la scena. La luce all'interno di una stanza ha una grande componente ambientale perchè le mura e gli altri oggetti presenti l'hanno riflessa più volte, al contrario una luce posizionata all'esterno, ad esempio in mezzo a un prato, ha una bassisima componente ambientale perchè non viene riflessa da nessun oggetto e si disperde nel buio.

Diffuse Light
La componente diffuse è la più importante e corrisponde alla descrizione che normalmente utilizziamo per la luce, ha una direzione ben precisa ma quando colpisce una superficie viene riflessa in modo equo in tutte le direzioni. Al contrario della componente ambientale che illumina allo stesso modo tutta la scena la componente diffuse illumina maggiormente i poligoni perpendicolari alla direzione dei suoi raggi e meno i poligoni che sono rivolti nelle altre direzioni. Tutte le fonti di luce che hanno una posizione o una direzione precisa hanno un alta componente diffuse.

Specular Light
La componente specular ha una direzione ben precisa e quando viene riflessa non si disperde in tutte le direzioni ma ne assume un'altra in base all'angolo di incidenza. La componente speculare viene spesso associata alla luminosità, ciò che permette ad un oggetto di sembrare lucido.

E' importante notare che il colore di un determinato oggetto sottoposto ad illuminazione non dipende solamente dalle componenti della luce, infatti tutte i poligoni sono contrassegnati con un determinato materiale il cui valore è dato da parametri simili a quelle delle luci che ne descrivono il comportamento. Ad esempio un materiale con un alto valore speculare, come il metallo, riflette molta più componente speculare e quindi apparirà più brillante di un materiale con una bassa componente speculare, come ad esempio la stoffa.

Abilitare l'illuminazione
Per poter usufruire dell'illuminazione dobbiamo prima attivarla:
glEnable(GL_LIGHTING);

Inoltre dobbiamo attivare le luci che abbiamo intenzione di utilizzare:
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT4);
    
Manipolare i parametri di illuminazione
Per modificare i parametri delle luci utilizziamo la famiglia di funzioni glLight*()
void glLight{if](GLenum light, GLenum pname, TYPE param);
void glLight{if]v(GLenum light, GLenum pname, TYPE *param);

light è l'identificativo della luce
pname è il parametro della da modificare;
param è il valore del parametro

Posizionare la luce
Per posizionare la luce utilizziamo il parametro GL_POSITION:

float position[4] = {0.0, 10.0, 0.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, position);

In questo modo abbiamo posizionato la luce in alto di 10 unità.
L'ultimo valore dell'array è sostanzialmente un flag che serve a indicare ad OpenGL se si tratta di una positional light oppure di una directional light.
Una positional light è una luce che viene posta nelle vicinanze della scena e illumina in tutte le direzioni a meno che non gli venga applicato un cono di illuminazione (spotlight) e si ottiene impostando l'ultimo valore dell'array a 1.0.
Una directional light è una luce che sta a una distanza virtualmente infinita dalla scena, l'esempio più lampante di directional light è il sole. La distanza infinita implica che i raggi della fonte di luce siano paralleli quando colpiscono gli oggetti della scena ottenendo così un effetto diverso da quello di una luce posizionata vicino i cui raggi non sono paralleli tra loro. Si ottiene settando il quarto valore dell'array a 0.0.
Quando utilizziamo una directional light gli altri valori dell'array non indicano più la posizione della fonte di luce bensì la direzione dalla quale la luce proviene.
Il codice seguente crea una directional light che proviene dalla asse z positivo e quindi illuminerà in direzione dell'asse z negativo:  

float position[4] = {0.0, 0.0, 1.0, 0.0};
glLightfv(GL_LIGHT0, GL_POSITION, position);

Creare una SpotLight
Come accennato prima possiamo trasformare una positional light in una spotlight applicando ad essa un cono di luce, una direzione e un valore di focus.
Per determinare l'ampiezza del cono modifichiamo il parametro GL_SPOT_CUTOFF che ci permette di impostare l'angolo tra l'asse della luce e il raggio più esterno, questo valore viene moltiplicato per 2 al fine di calcolare l'intero diametro della luce. Solitamente la spotlight è disabilitata e i raggi irradiano a 360°, questo vuol dire che il parametro di CUTOFF è di 180°. Il massimo valore che è consentito impostare (a parte quello speciale di 180° che serve a disabilitare la spotlight) è di 90° dal quale risulterebbe un cono di 180°.
Per indicare la direzione modifichiamo il parametro GL_SPOT_DIRECTION e passiamo un vettore x,y,z che contenga la direzione della luce.
Infine è possibile modificare il focus della spotlight tramite GL_SPOT_EXPONENT che influisce sulla concentrazione della luce al centro della spotlight, quando assume un valore molto alto avremo una luce molto intensa al centro del cono e via via più attenuata all'esterno, se il suo valore è uguale a 0.0 la luce sarà ugualmente intensa in tutte le parti del cono.

Colore e Intensità
Per impostare il colore e l'intensità delle varie componenti della luce utilizziamo la funzione glLight*() con i seguenti
parametri ognuno dei quali modifica una delle componenti analizzate precedentemente:

- GL_AMBIENT
- GL_DIFFUSE
- GL_SPECULAR

I vettori da specificare devono contenere le componenti RGBA.
Ad esempio il seguente codice:

float light_diffuse[4] = {0.0, 1.0, 0.0, 1.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
float light_specular[4] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);

imposta il colore verde per la componente diffuse e il colore bianco per la componente specular.

Attenuazione  
Nella realtà l'intensità della luce diminuisce all'aumentare della distanza. Anche nella nostra scena possiamo riprodurre questo effetto attraverso i parametri di attenuazione:
- GL_CONSTANT_ATTENUATION (Default = 1.0)
- GL_LINEAR_ATTENUATION    (Default = 0.0)
- GL_QUADRATIC_ATTENUATION (Default = 0.0)

Le conseguenze sull'intensità sono l'effetto della seguente funzione matematica:
AttenuationFactor = 1 /  kc + kl * d + kq * d^2
kc è la GL_CONSTANT_ATTENUATION
kl è la GL_LINEAR_ATTENUATION
kq è la GL_QUADRATIC_ATTENUATION
d è la distanza dalla fonte di luce

Light Model
OpenGL ci mette a disposizione la famiglia di funzioni glLightModel*() per settare alcuni parametri globali:
void glLightModel{if}(GLenum pname, TYPE param);
void glLightModel{if}v(GLenum pname, TYPE *param);

pname è il parametro da modificare
param è il valore del parametro

I parametri disponibili sono:
- GL_LIGHT_MODEL_AMBIENT
- GL_LIGHT_MODEL_LOCAL_VIEWER
- GL_LIGHT_MODEL_TWO_SIDE

Il primo parametro ci permette di settare un luce di ambiente globale, cioè che non proviene da nessuna delle 8 luci di OpenGL:

float lightmodel_ambient[4] = {0.4, 0.0, 0.0, 1.0};
glLightModelfv(lightmodel_ambient);

Gli oggetti nella scena in questo caso saranno influenzati da una tenue luce rossa e saranno quindi visibili anche se tutte le luci sono disabilitate.

GL_LIGHT_MODEL_LOCAL_VIEWER può avere come valore GL_FALSE o GL_TRUE. Si tratta di decidere in base a quale vettore calcolare gli effetti della luce speculare. Per capire il suo funzionamento dobbiamo dare una occhiatoa ai passi per calcolare la componente specualare su un oggetto che sono i seguenti:

s = lighdirection + viewpoint<
Normalize(s)

lighdirection è il vettore che parte dal vertice e punta verso la luce
viewpoint è il vettore che rappresenta la direzione dal quale proviene il nostro sguardo;
s è la somma di questi due vettori chee viene normalizzata

Ls = (s * n) ^ GL_SHININESS * specularlight * specularmaterial

Ls è il vettore dove verranno salvati i valori di colore da applicare al poligono
n è il vettore normale del vertice
GL_SHININESS è il valore che indica la brillantezza di un materiale
specularlight e specular material sono i valori della compoenente speculare rispettivamente di luce e materiale.

Il parametro GL_LIGHT_MODEL_LOCAL_VIEWER agisce sul vettore viewpoint, se è impostato a GL_TRUE verrà usata la reale posizione dell'osservatore e la riproduzione dell'effetto sarà più vicina alla realtà, se è uguale a GL_FALSE viene considerato il viewpoint infinito (0.0, 0.0, 1.0), ciò permette un aumento di prestazioni perchè questo valore è costante a scapito però della fedeltà.

Infine il parametro GL_LIGHT_MODEL_TWO_SIDE ci permette di abilitare l'illuminazione anche per le facce interne, cioè per la parte "dietro" dei nostri poligoni. Semplicemente OpenGL calcola l'inverso dei vettori normali indicati per la faccia frontale e calcola l'illuminazione. Naturalmente ciò provoca un rallentamento delle prestazioni poichè le operazioni devono essere seguite 2 volte per ogni poligono.  

OpenGL, specifiche standard ed estensioni
Autore: HTC - Ultimo Aggiornamento: 2004-03-31 22:18:12 - Data di creazione: 2004-03-31 22:18:12
Tipo Infobox: DESCRIPTION - Skill: 2- JUNIOR

La libreria grafica OpenGL e' in continuo sviluppo. Negli ultimi anni sono stati redatti diversi standard, l'ultima versione e' la 1.5 rilasciata nell'estate 2003. Oltre a queste specifiche adottate ufficialmente dall'ARB diverse aziende hanno sviluppato nuove funzioni non standard che hanno portato alla realizzazione di implementazioni diversificate tra loro, sia nella versione dello standard adottato sia nel numero e nel tipo delle estensioni non standard supportate. Questo modo di operare pur dando la massima liberta' di sviluppo ha avuto come conseguenza non poca confusione e disorientamento tra utenti e sviluppatori.

Una degli obiettivi progettuali di OpenGL, a partire dalla versione 1.1, era quello di garantire un meccanismo per la gestione delle estensioni attraverso il quale le nuove implementazioni potevano fornire features aggiornate e tenere il passo con le nuove tecnologie senza dover obbligare gli utenti con implementazioni piu' vecchie ad aggiornare l'hardware del proprio sistema. In sostanza questo meccanismo permette di controllare se il sistema fornisce una determinata estensione, se quest'ultima e' presente verra' utilizzata altrimenti l'applicazione puo' scegliere se adottare una tecnica piu' lenta per aggirare il problema oppure terminare con una segnalazione.

Nuovi standard ed estensioni

Dopo aver stabilito uno standard di riferimento, per mantenere vivo lo sviluppo della libreria e' stata lasciata la possibilita' alle aziende facenti parte dell'ARB di inserire delle funzioni personalizzate a fianco di quelle standard all'interno delle proprie implementazioni.
Ecco i tipi di estensioni OpenGL piu' comuni:

HP   – Hewlett-Packard
IBM  – International Business Machines
KTX  – Kinetix (3D Studio Max)
INTEL– Intel
NV   – NVIDIA Corporation
MESA – Implementazione software OpenGL di Brian Paul
SGI  – Silicon Graphics
SGIX – Silicon Graphics (sperimentale)
SUN  – Sun Microsystems
WIN  – Microsoft

Ad esempio NVIDA puo' fornire una propria estensione OpenGL che e' disponibile solo agli utenti dotati di una scheda NVIDA di ultima generazione.

Se una estensione si rivela particolarmente utile puo' essere che altre aziende comincino ad utilizzarla, in questo caso l'estensione perde il riferimento all'azienda che l'ha promossa e acquista il prefisso EXT. Infine se questa estensione e' molto diffusa dopo un certo periodo di tempo viene resa ufficiale dall'Architecure Review Board e assume il prefisso ARB.

Le estensioni ufficialmente riconosciute vengono prese in considerazione quando si tratta di definire un nuovo standard. Ad esempio le specifiche di OpenGL 1.2 sono composte dalle funzioni delle versioni precedenti piu' le estensioni EXT e ARB che si sviluppate dopo il rilascio del vecchio standard 1.1.

Come ottenere le nuove versioni di OpenGL

Naturalmente e' bene tenere aggiornato il proprio sistema in modo da poter godere a pieno delle nuove applicazioni che sfruttano OpenGL e il modo piu' semplice per farlo e' installare l'ultima versione di OpenGL.
In realta', pero', non c'e' un unico file binario che ci permetta di accedere all'ultima versione ma bisogna aggiornare il sistema indirettamente.
Dato che OpenGL fornisce lo standard ma non l'implementazione tocca alle case che forniscono le schede video cablare sulle proprie schede le ultime estensioni OpenGL. Inoltre sempre a loro tocca fornire il software da installare sulla macchina (i driver) che sia in grado di accedere a queste funzioni.
  
Sia su sistemi Windows che su sistemi Linux e' quindi necessario installare i driver aggiornati della propria scheda video. Senza l'aggiornamento una nuova applicazione che tenta di accedere alle estensioni si blocchera' oppure dovra' simulare lei stessa la funzione richiesta via software con evidente perdita di performance.

I driver aggiornano l'implementazione di OpenGL alla versione supportata della scheda. In questo modo l'applicazione puo' accedere alle estensioni che nel migliore di casi saranno implementate in hardware. Se invece l'estensione non e' cablata, ad esempio su una scheda superata, i driver simuleranno almeno in software le nuove funzioni che non sono implementate in hardware. Attenzione pero', le implementazioni delle estensioni fornite dai driver, pur non essendo all'altezza di quelle stampate direttamente sulla scheda saranno comunque molto piu' veloci di quelle che un eventuale applicazione potrebbe fornire poiche' chi ha scritto i driver conosce la scheda su cui si sta lavorando e puo' fare delle ottimizzazioni specifiche.

Solitamente in ambiente Linux le distribuzioni sono dotate della libreria Mesa. Mesa e' una implementazione software di OpenGL, la versione attuale e' la 6.0 e supporta pienamente le specifiche dello standard 1.5. Essendo Mesa una libreria software e' molto lenta ma fortunatamente essa non e' fornita stand-alone bensi' come parte dei driver XFree86/DRI (Direct Rendering Infrastructure) che permette di avere prestazioni accettabili.
In ogni caso e' bene utilizzarla solo nei seguenti casi:

- La scheda video non supporta OpenGL (ad esempio Matrox)
- Non sono disponibili driver aggiornati per la scheda
- La scheda video e' molto vecchia e supporta uno standard OpenGL superato

Per quanto riguarda la libreria GLU l'ultima versione disponibile e' la 1.3 che e' compresa nel codice sorgente di Mesa, anche se e' stata sviluppata dalla SGI, ed e' quindi gia' integrata in XFree86.

In ogni caso e' bene consultare il sito della casa madre della scheda video per avere maggiori informazioni.
Per quanto riguarda l'aggiornamento del proprio sistema Linux e' utile visitare i siti della libreria Mesa 3D, del  Direct Rendering Open Source Project  ed infine il sito del server grafico  XFree86 .

OpenGL Vs DirectX
Autore: HTC - Ultimo Aggiornamento: 2004-03-31 22:16:04 - Data di creazione: 2004-03-31 22:16:04
Tipo Infobox: ETCETERA - Skill: 2- JUNIOR

Sono molteplici le discussioni che hanno per oggetto le differenze tra OpenGL e DirectX e che spesso degenerano in flames. In realtà le prestazioni e le feature disponibili sono simili come pure la Rendering Pipeline di base. Le differenze si fanno più acute sotto altri aspetti.

Innanzitutto DirectX è una libreria che gira solamente sul sistema operativo Windows e sulla console di casa Microsoft XBox. Al contrario OpenGL è gestita dall'ARB (Architecture Review Board) e si tratta di una libreria multipiattaforma. Ne consegue che le procedure di aggiornamento e di sviluppo della libreria stessa sono molto diverse. Questo spiega come le DirectX siano attualmente alla versione 9.0 e vengano regolarmente aggiornate mentre l'attuale standard OpenGL è giunto solamente alla versione 1.5 e le nuove features sono introdotte in modo apparentemente caotico.

Una differenza fondamentale quando si parla di DirectX e OpenGL riguarda le aree di responsabilità. Infatti sarebbe formalmente più corretto parlare di DirectX Graphics e ancora meglio di DirectDraw e Direct3D.
DirectX non è solamente una libreria grafica ma è un tool di sviluppo completo per la realizzazione di applicazioni multimediali e si estende a diversi campi, esso comprende:
DirectDraw - Libreria per la grafica 2D
Direct3D - Libreria per la grafica 3D
DirectSound - Libreria per la riproduzione e la manipolazione di effetti sonori
DirectInput- Libreria per la gestione dell'Input (tastiera, mouse, joystick etc.)
DirectShow - Libreria per la riproduzione di file video
DirectPlay - Libreria per il networking

DirectX è stata creata per favorire lo sviluppo di videogiochi e altre applicazioni simili su piattaforma Windows. Tali applicazioni infatti necessitano di molte risorse e devono essere in grado di sfruttare a fondo il potenziale dell'hardware. In ambiente DOS questo era possibile grazie alla possibilità di comunicare direttamente con le periferiche, a partire da Windows 95 data l'architettura complessa progettata per i programmi convenzionali il sistema operativo fornisce una interfaccia troppo lenta e macchinosa per raggiungere risultati apprezzabili in campo multimediale.
DirectX permette di accellerare l'accesso all'hardware ed evitare i comuni canali di comunicazione di Windows in modo da incrementare sensibilmente le performance. Non solo, DirectX riveste due ruoli, quello di driver veloce e di API. Non è possibile dividere queste due funzioni.
Ciò significa che un programma che sfrutta OpenGL non può appoggiarsi a DirectX per avere una via preferenziale verso la scheda video, infatti tale via è utilizzabile solamente se il canale viene aperto dalle API Direct3D (o DirectDraw) e se vengono utilizzate le routine grafiche proprie di tali API.
Quando si utilizza OpenGL il compito di aggirare le normali procedure di Windows è affidato alle GL Extension del sistema operativo (WGL).
Il secondo obiettivo di DirectX è quello di fornire una interfaccia di programmazione standard indipendente dalla reale capacita' della periferica. Grazie all'architettura HAL/HEL (Hardware Abstraction Layer e Hardware Emulation Layer) DirectX, dopo aver individuato le capacità dell'hardware, durante l'esecuzione dell'applicazione è in grado di sfruttare la scheda se una determinata feature è supportata, in caso contrario la feature in questione verrà emulata via software. L'applicazione perderà in prestazioni ma continuerà a girare. Inoltre questo facilita lo sviluppo del software dato che durante la fase di progettazione non è necessario trattare le  problematiche relative all'aggiramento di eventuali lacune sulla macchina dell'utente finale.
E' necessario dire che, al pari di OpenGL, determinate funzioni delle API DirectX vengono ora supportate direttamente sulla scheda o dai relativi driver.

Infine DirectX, a differenza di OpenGL, sembra più difficile da capire e da sfruttare, almeno inizialmente. Si tratta naturalmente di una considerazione puramente soggettiva anche se è dovuta in parte al diverso tipo di interfaccia, chiamate di funzione in OpenGL e tecnologia COM per DirectX.

Il consiglio è di non escludere a priori una delle librerie e in base ai propri obiettivi e gusti personali scegliere quella da approfondire. Spesso, inoltre, diversi videogiochi di successo utilizzano OpenGL come libreria grafica ma affidano a DirectX altri compiti importanti come la gestione dell'input e degli effetti sonori.

OpenGL Buffers
Autore: HTC - Ultimo Aggiornamento: 2004-09-22 05:43:55 - Data di creazione: 2004-09-22 05:43:55
Tipo Infobox: DESCRIPTION - Skill: 3- INTERMEDIATE

OpenGL utilizza diversi buffer per mantenere in memoria le informazioni riguardanti i pixel dell'area di rendering.
I buffer differiscono tra loro per il tipo di informazioni che contengono o per la loro posizione.
L'insieme di tutti i buffer si definisce OpenGL Frame Buffer.

Il ruolo svolto dai buffer in OpenGL e' essenziale, a secondo del loro ruolo essi memorizzano  particolari informazioni su ogni pixel del frame che si sta renderizzando.
I buffer messi a disposizone da OpenGL sono:

Color Buffer - Contiene le informazioni riguardanti il colore dei pixel
Depth Buffer o Z Buffer - Contiene informazioni riguardo la profondità dei pixel
Stencil Buffer - Contiene le informazioni per eventuali mask da applicare
Accumulation Buffer - E' un buffer dove è possibile accumulare le immagini per ottenere effetti speciali
Auxiliary Buffer - Sono dei buffer colore ausiliari che possono essere utilizzati come "aree di lavoro"

Le applicazioni non sono costrette ad utilizzare tutti i buffer disponibili, infatti ogni programma OpenGL prima di iniziare qualsiasi operazione di rendering si occupa di selezionare e attivare un Frame Buffer adatto alle proprie esigenze.

Color Buffer
Il buffer del colore è senza dubbio il più importante, esso è indispensabile dato che memorizza il colore di ogni pixel del frame. OpenGL mette a disposizione due tipi di color buffer:
- RGBA
- Index

La modalità più diffusa è quella RGBA dato che consente di memorizzare le informazioni di colore per ogni componente (Red, Green, Blue e Alpha), essa consente un maggiore numero di colori e la possibilità di creare effetti speciali altrimenti impossibili con le vecchia modalità Index.
Normalmente la dimensione del color buffer è di 32 bit, 8 bit (un byte dunque) per ognuna delle componenti.
E' però possibile creare buffer non simmetrici o addirittura privi di un canale (a volte il canale Alpha viene impostato a 0 bit se non si necessita di effettuare trasparenze o effetti simili).
E' possibile richiedere a OpenGL più di un color buffer, specificando l'opzione Double Buffer e/o Stereo Buffer.
Quando chiediamo ad OpenGL un double buffer essa crea due buffer colore, uno principale (Front buffer) e uno nascosto (Back buffer). Le operazioni di disegno avvengono sul back buffer invisibile all'utente, quando il frame è completo il due buffer vengono swappati trasformando il back buffer nel buffer principale visualizzato a schermo e il front buffer nel buffer nascosto.
Specificando l'opzione Stereo Buffer invece OpenGL ci offre due buffer principali denominati buffer sinistro e buffer destro che consentono di creare una immagine simile a quella creata dalla sovrapposizione della vista dell'occhio sinistro e dell'occhio destro.
Specificando entrambe le opzioni si arriva a disporre fino a 4 buffer colore (left front, right front, left back, right back).

Depth Buffer o Z Buffer
E' il buffer della profondità, ad ogni pixel è associata una determinata profondità che naturalmente dipende dalla sua posizione all'interno della scena. Un pixel appartenente ad un oggetto molto lontano un alto valore di profondità mentre un oggetto molto vicino alla "camera" avrà un valore molto basso.
Questo buffer è indispensabile per visualizzare gli oggetti in base alla distanza dal punto di vista invece che in base all'ordine nel quale vengono disegnati.
Di norma tutte le applicazioni OpenGL utilizzano il Depth Buffer e la sua dimensione è di solito di 16 bits con evidentemente 2^16 livelli di profondità.

Stencil Buffer
Lo Stencil buffer permette di renderizzare sul frame buffer attraverso una maschera che ci consente di disegnare solo su alcune porzioni del frame.
Per creare una maschera dobbiamo renderizzare sullo stencil buffer, per ogni pixel che andremo a modificare verrà memorizzato un 1. Renderizzando sempre sullo stesso frame un nuovo oggetto possiamo indicare di modificare un pixel solo se il valore relativo al dato pixel nello stencil buffer è uguale 1 ovvero appartenente alla maschera.
In questo modo il nuovo oggetto verrà renderizzato solo all'interno dell'area precedentemente delimitata.
In base alla dimensione in bit dello stencil buffer è possibile creare diversi strati di maschere.
Viene utilizzato per le ombre realistiche, riflessioni, filtri, rendering all'interno
di forme irregolari.

Accumulation Buffer
L'accumulation buffer è utilizzato per ottenere effetti speciali mediante l'accumulazione di diverse immagini, permette di ottenere quello che in fotografia è conosciuto come sovra-esposizione.
L'accumulation buffer di norma ha un numero di bit per canale doppio rispetto a quello del color buffer ed è piuttosto lento dato che raramente è supportato direttamente in hardware.
Viene utilizzato per soft shadows, motion blur, effetto depth field etc.

Privacy Policy