1. TECNICHE DISCRETE
  2. Buffers e Mappings

I metodi di mapping sono delle tecniche che consentono allíutente di creare líillusione di visualizzare superfici di grande complessità, anche utilizzando semplicemente dei poligoni. Queste tecniche sono applicate durante il processo di rendering, e sono basate su interazioni dirette tra líutente ed il frame buffer, o altri buffer bidimensionali discreti, ovvero sulla possibilità di leggere e scrivere direttamente i singoli pixel.

I buffer hanno una natura inerentemente discreta, ed hanno una risoluzione limitata, sia spaziale che in profondità. Possiamo definire un buffer bidimensionale come un blocco di memoria con una risoluzione spaziale di n ¥ m elementi, di k bit ciascuno.

Figura 1.1 Buffer.

Per il frame buffer la risoluzione spaziale n ¥ m è uguale alla risoluzione dello schermo, e k è determinato dal numero di colori che il sistema grafico può visualizzare. Nel caso del depth buffer, n e m sono ancora determinati dalla risoluzione dello schermo, mentre k è determinato dalla risoluzione in profondità che il sistema può sopportare.

Una delle applicazioni più interessanti dei buffer riguarda la visualizzazione delle superfici. Il processo di modellazione di un oggetto con un insieme di primitive geometriche ha delle limitazioni, soprattutto se si vogliono rappresentare oggetti e superfici di una certa complessità. Supponiamo ad esempio di voler ottenere líimmagine di una arancia. Mentre rendere le sue proprietà globali, come forma, dimensione e colore, non è un compito difficile, ottenere i dettagli superficiali e simulare quella casualità che si può osservare sulla sua buccia, è un compito che richiede la generazione di un numero estremamente alto di poligoni.

Líidea di base delle tecniche di mapping è quella di non cercare di costruire modelli progressivamente più complessi, ma invece di costruire un modello semplice, e poi aggiungervi i dettagli nel corso del processo di rendering. Il rendering di una superficie, sia un poligono che una superficie curvilinea, si esegue suddividendo la superficie in pezzi molto piccoli, chiamati frammenti, ciascuno dei quali, una volta proiettato, ha al più la dimensione di un pixel. Durante il processo di rendering, si deve assegnare una gradazione di colore ad ogni frammento, scegliendo un modello di shading. Líazione degli algoritmi di mapping consiste nel modificare líalgoritmo di shading sulla base di un vettore bidimensionale, la mappa, che viene usato per modificare i colori assegnati, oppure i parametri della superficie, ad esempio le proprietà dei materiali e i vettori normali. Ci sono tre diversi metodi di applicazione delle tecniche di mapping:

  1. texture mapping
  2. bump mapping
  3. environmental mapping.

Il texture mapping utilizza un motivo (nel seguito utilizzeremo sempre il termine inglese pattern) per determinare il colore dei frammenti. I pattern possono essere determinati da motivi regolari, come quelli resi disponibili dai sistemi grafici per il riempimento dei poligoni, da metodi procedurali di generazione, oppure da immagini digitalizzate. In tutti i casi, líimmagine è prodotta per mezzo della proiezione - mapping - di un pattern sulla superficie. In altre parole, il metodo del texture mapping consiste nel visualizzare i dettagli delle superfici proiettando dei pattern su superfici lisce.

Líapproccio seguito dal bump mapping consiste invece nel deformare la superficie per creare delle variazioni. Líenvironmental mapping consiste infine nel proiettare líimmagine dellíambiente circostante su una superficie riflettente durante il processo di rendering.

I tre approcci hanno molto in comune. In tutti e tre lo shading dei pixel individuali viene alterato, ed inoltre essi sono tutti implementati nel corso del processo di shading.

  1. Texture Mapping

Il termine inglese texture si utilizza per indicare la struttura superficiale degli oggetti, ovvero i motivi (pattern) che la caratterizzano. Questi possono variare da motivi regolari, come righe e scacchiere, fino a pattern più complessi in grado di caratterizzare la struttura superficiale dei materiali naturali. Nel mondo reale, possiamo distinguere gli oggetti di forma e dimensione simili, proprio in base al loro texture.

Líidea degli algoritmi di texture mapping è di estendere le capacità grafiche e visualizzare oggetti virtuali dettagliati, proiettando un texture sulla superficie degli oggetti geometrici creati.

Figura 1.2 Texture mapping.

Il texture mapping bidimensionale richiede líesecuzione di una sequenza di passi, che possono essere facilmente estesi anche al caso di texture tridimensionali. Il punto di partenza è un texture pattern T(s,  t). Le variabili indipendenti s e t sono chiamate coordinate texture. La funzione T può essere memorizzata in una memoria texture come un vettore n ¥ m di elementi, chiamati texel. Senza perdita di generalità, supponiamo che le coordinate texture siano riferite allíintervallo (0, 1).

Una texture map è una funzione che associa un texel ad ogni punto della superficie di un oggetto geometrico, e poi proietta questi punti sullo schermo. Si tratta dunque di una funzione matematica che trasforma le coordinate texture (st) in coordinate geometriche (xy , z), accoppiata ad una funzione proiezione che trasforma le coordinate geometriche in coordinate dello schermo (x5y5). Se definiamo líoggetto geometrico usando delle superfici parametriche dobbiamo considerare una funzione mapping addizionale. In questo caso, ci sono infatti due mapping concorrenti: il primo dalle coordinate texture alle coordinate geometriche, e il secondo dalla coordinate parametriche (uv) alle coordinate geometriche. Un terzo mapping proietta infine líoggetto sullo schermo del display.

Figura 1.3 Texture mapping per una superficie parametrica.

Concettualmente, il processo di texture mapping è semplice. Uníarea limitata del texture viene proiettata su uníarea della superficie geometrica che corrisponde ad un pixel dellíimmagine finale. I valori di T (che ad esempio possono rappresentare i colori espressi nel sistema RGB) sono usati per modificare il colore della superficie, oppure per assegnare un colore alla superficie solo sulla base del valore del texel. Questo assegnamento di colore è eseguito nel corso dello shading.

Un esame più attento mette in evidenza alcune difficoltà. Per prima cosa, è necessario determinare la funzione che trasforma le coordinate texture in coordinate geometriche. Un texture in due dimensioni è di solito definito su una regione rettangolare, e la proiezione di questo rettangolo su una regione arbitraria nello spazio tridimensionale potrebbe essere espressa da una funzione estremamente complessa, o potrebbe avere proprietà indesiderabili. Ad esempio, non è possibile proiettare un rettangolo su una sfera senza una distorsione di forme e distanze. In secondo luogo, a causa della natura del processo di rendering, in cui si lavora pixel per pixel, è necessario determinare la trasformazione inversa dalle coordinate dello schermo alle coordinate texture. Quando si valuta lo shade di un pixel, si deve infatti determinare quale punto nellíimmagine texture deve essere usato, e questo calcolo richiede di passare dalla coordinate dello schermo alle coordinate texture. Una terza difficoltà sorge infine perché nel processo di shading si determina lo shade di ogni singolo pixel, e un pixel corrisponde ad un piccolo rettangolo sulla superficie del display. Dobbiamo dunque trasformare non punti in punti, ma piuttosto aree in aree e, in una tale situazione, si possono verificare problemi di aliasing.

Prima di affrontare il problema di come trovare il mapping inverso, consideriamo il problema dellíassegnamento delle gradazioni di colore. Una possibilità è usare il punto che si ottiene proiettando indietro il centro del pixel per trovare un valore texture. Questa tecnica è semplice, ma soggetta a seri problemi di aliasing, che risultano particolarmente visibili se il texture è periodico. Questo problema è illustrato nella Figura 1.4, dove abbiamo un texture periodico e una superficie piatta. La proiezione allíindietro del centro di ogni pixel cade sempre tra due linee scure, e di conseguenza il valore del texel corrisponde sempre al colore chiaro.

Figura 1.4 Il problema dellíaliasing.

Una strategia migliore, ma più difficile da implementare, consiste nellíassegnare il valore texture definito dalla media dei texel in un intorno del punto. Anche questo metodo risulta tuttavia imperfetto. Ad esempio, nel caso illustrato in Figura 1.4, ciò porterebbe ad assegnare uno shade medio, senza riuscire a riprodurre il motivo a strisce del texture. Inoltre, gli effetti di aliasing persistono a causa della risoluzione limitata sia del frame buffer che della mappa del texture. Questi problemi sono tanto più visibili, quanto più il pattern del texture è regolare.

Tornando al problema del mapping inverso, data una superficie parametrica, si può trasformare un texel T(st) in un punto della superficie p(uv) con le funzioni lineari

Se ae bd, questa trasformazione è invertibile. Il mapping lineare risulta facile da applicare, ma presenta la limitazione di non tenere conto della curvatura della superficie.

Un altro approccio al problema del mapping consiste nellíapplicare una trasformazione in due fasi. Nella prima fase si esegue il mapping del texture su una superficie intermedia semplice, ad esempio una sfera, un cilindro, o un cubo. Nella seconda fase la superficie intermedia, su cui è stato proiettato il texture, è proiettatta sulla superficie finale che si vuole visualizzare.

Supponiamo di usare un cilindro di altezza h e raggio r come superficie intermedia. I punti sul cilindro sono rappresentati dalle equazioni parametriche

dove u e v variano nellíintervallo (0, 1). Se anche le coordinate texture variano nello stesso intervallo, possiamo applicare la trasformazione

s = u,

t = v.

Utilizzando solo la parte curva del cilindro, e non le sue basi, siamo dunque in grado di proiettare il texture senza modificarne la forma.

Figura 1.5 Texture mapping su un cilindro.

Nella seconda fase, occorre proiettare i valori texture dalla superficie intermedia alla superficie finale. Una possibile strategia consiste nel prendere il valore texture in un punto sulla superficie intermedia, nel muoversi da questo punto lungo la direzione del vettore normale fino ad intersecare la superficie finale, e infine nellíassociare il valore del texture al punto di intersezione. Si può anche invertire il metodo: ci si può quindi muovere da un punto sulla superficie finale, lungo il vettore normale, fino ad intersecare la superficie intermedia, e leggere il texel corrispondente al punto di intersezione. Una terza opzione, applicabile se si conosce il centro dellíoggetto finale, consiste nel tracciare una linea dal centro ad un punto sulla superficie dellíoggetto, e nel calcolare líintersezione di questa linea con la superficie intermedia. Il texel nel punto di intersezione con la superficie intermedia è quindi assegnato al punto corrispondente sulla superficie finale.

  1. Texture Mapping in OpenGL

In OpenGL i textures bidimensionali possono essere specificati dal comando:
glTexImage2D(GL_TEXTURE_2D, level, components, width, height, border, format, type, image);

Il pattern da proiettare è memorizzato nel vettore image, di dimensioni width  height. Il valore components è il numero (da 1 a 4) di componenti di colore che si vogliono influenzare con la tecnica di mapping. I parametri level e border consentono di controllare e manipolare il texture. In OpenGL è possibile definire dei texture a risoluzione multipla, che possono essere utilizzati per minimizzare i problemi di aliasing. Ci sono naturalmente molti parametri coinvolti nella specificazione di un texture, comunque un esempio semplice è dato dalla funzione
glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, my_image);

con la quale si definisce in vettore my_image, di dimensioni 512  512, nel sistema di colori RGB, le cui componenti sono byte variabili nellíintervallo da 0 a 255. Il vettore my_image può essere definito allíinterno del programma, oppure può essere letto da una memoria esterna.

Il metodo di base per implementare il texture mapping in OpenGL consiste nellíassegnare le coordinate texture ad ogni vertice, nello stesso modo in cui si assegnano colore e vettori normali. Le coordinate texture sono quindi assegnate ai frammenti per interpolazione. A questo scopo, si utilizzano diverse forme della funzione glTexCoord. Se stiamo usando numeri in virgola mobile e texture bidimensionali, la chiamata della funzione assume la seguente forma:
glTexCoord3f(s,t);

OpenGL permette inoltre di controllare il mapping più in dettaglio, attraverso un certo numero di parametri. Possiamo predisporre dei parametri per definire come trattare i valori di s e t fuori dallíintervallo (0, 1); per specificare come risolvere il problema creato dal fatto che líarea di un singolo pixel non corrisponde a quella di un texel; e per specificare se si vuole che il texture determini totalmente il colore di un pixel, oppure se si preferisce usare il prodotto del colore texture e del colore associato al vertice per determinare il colore del pixel. OpenGL può anche generare le coordinate texture automaticamente, con la funzione glTexGen.

  1. Generazione del texture

Uno delle potenzialità più importanti del texture mapping è quella di consentire un ampio livello di dettaglio senza generare troppi oggetti geometrici. I sistemi grafici, come SGIís Reality Engine, possono eseguire il texture mapping tridimensionale in tempo reale. Il texture è proiettato sullíoggetto nel corso del processo di rendering, con la stessa velocità con cui vengono elaborati gli altri oggetti, non soggetti allíapplicazione del texture. Ad esempio, si può simulare un prato in una scena proiettando líimmagine di un prato ottenuta dallo scanner di una fotografia, e il tempo richiesto è molto minore di quello necessario per generare degli oggetti in 2 o 3 dimensioni con cui approssimare líimmagine del prato.

I texture mapping possono essere generati anche con tecniche procedurali. Di particolare interesse sono i pattern osservabili in natura (ad esempio di sabbia, prati, o minerali). Questi patterns mostrano sia una struttura, che una considerevole casualità. La maggior parte dei metodi di generazione algoritmica di texture utilizza quindi dei generatori di numeri casuali, il cui output è successivamente filtrato. Un generatore ideale di numeri casuali produce una sequenza di valori statisticamente indipendenti, il cosiddetto rumore bianco. Il filtro è usato per introdurre della correlazione tra valori successivi di rumore, simulando così la sovrastruttura globale del pattern. Controllando il filtro, è possibile simulare diversi pattern. Si può anche utilizzare il generatore di numeri casuali per generare il texture direttamente.

Le tecniche casuali sono state applicate soprattutto per creare texture tridimensionali. I texture tridimensionali presentano molti vantaggi pratici. Infatti, associando il valore T(str) direttamente ad ogni punto (xyz), si può interamente evitare il problema del mapping.

  1. Environmental mapping

Le superfici altamente riflettenti sono caratterizzate da riflessioni speculari che rispecchiano líambiente circostante. Le immagini specchiate da queste superfici possono essere prodotte applicando la tecnica ray-tracing, che risulta tuttavia troppo costosa per essere utilizzata in pratica. Uníaltra possibilità è invece quella di estendere le tecniche di mapping per ottenere uníimmagine che approssimi la riflessione desiderata. Si parla in questo caso di environmental map o di mappe di riflessione.

Líeffetto della riflessione speculare si può ottenere in due fasi. Nella prima fase si genera uníimmagine dellíambiente esterno su una superficie di proiezione intermedia. Il centro di proiezione viene posizionato nel centro dellíoggetto riflettente, ma le proiezioni sono calcolate immaginando che líoggetto sia stato rimosso dalla scena. Se ad esempio líambiente circostante è racchiuso in una stanza, líoggetto intermedio più naturale da scegliere è una scatola quadrata. In questo caso, si calcolano quindi sei proiezioni, corrispondenti alle quattro pareti, al pavimento e al soffitto. A questo punto, il mapping environmental può essere trattato esattamente come il texture mapping. Si riposiziona líoggetto nella scena, e si trasferiscono le proiezioni intermedie dellíambiente sulla sua superficie.

  1. Bump mapping

La tecnica del bump mapping consiste nel modificare la forma apparente di una superficie, perturbando i vettori normali quando la superficie viene visualizzata. I colori generati dallo shading mostreranno così una variazione delle proprietà della superficie.

La normale in un punto della superficie caratterizza la forma della superficie in un intorno di quel punto. Perturbando le normali ad ogni punto sulla superficie di un piccolo ammontare, si crea una superficie che presenta molte piccole variazioni. Applicando la perturbazione durante la fase di rendering, si può ottenere una superficie dallíaspetto molto complesso. Poiché le perturbazioni sono applicate ai vettori normali, i calcoli di shading devono essere corretti facendo riferimento alla superficie modificata.

Le normali possono essere perturbate in vari modi. Nel caso di superfici parametriche, una procedura che risulta efficiente è la seguente. Sia p(uv) un punto su una superficie parametrica. Il vettore di modulo unitario, normale alla superficie in questo punto si ottiene valutando il prodotto vettoriale dei vettori delle derivate parziali:

,

dove

La deformazione d(uv), applicata nella direzione del vettore normale, perturba il punto p:

pí = p + d(u,v) n,

e la normale nel punto perturbato è definita dal prodotto vettoriale

.

Le derivate parziali possono essere calcolate differenziando líequazione che definisce pí, trascurando i termini che sono moltiplicati per la funzione bump (infatti, per ipotesi si assume | d(u,v) | ´ 1) e calcolando il prodotto vettoriale. Si ottiene così il risultato

.

Per applicare il bump mapping occorrono due vettori in cui memorizzare le derivate parziali della funzione bump rispetto a u e a v. Questi vettori possono essere precalcolati, con metodi simili a quelli usati per la generazione dei texture, e le normali possono essere perturbate durante il processo di shading.