Texture Mapping
Cosa è Il Textuere Mapping? Il texture mapping é un processo di disegno grafico in cui una superfice bidimensionale(2-D),chiamata Texture map, viene “avvolta” a un oggetto tridimensionale(3-D).In questo modo l’oggetto 3-D acquisisce una superfice texture simile a quella 2-D. Il texture mapping è quindi l’equivalente elettronico di applicare ,una carta da parato,della pittura o della vernice a un oggetto reale.
Ancora… 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à) , 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
Come texturizzare un oggetto: Per texturizzare un oggetto dobbiamo creare una texture partendo dall'immagine che vogliamo applicare. La texture è un tipo di dato,usato per memorizzare l’immagine stessa da applicare all’oggetto e gestito direttamente dalla libreria grafica di basso livello (OpenGL) ;perchè bisogna eseguire diverse operazioni per adattare l'immagine all'oggetto. GLuint texture[1]; // Storage For One Texture
Ancora… L’ immagine solitamente viene visualizzata come un rettangolo(o quadrato) 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,traslazioni etc.) l'immagine sia sempre visualizzata in modo corretto. L'altezza e la larghezza dell'immagine DEVE essere un multiplo di 2. Altezza e larghezza devono essere di almeno 64 pixels e, per motivi di compatibilità, non devono essere maggiori di 256 pixels Vediamo un esempio…
Ancora.. (u1,v1) (u0,v0) s (u3,v3) t (u2,v2)
Ancora… Object -> Texture Transformation Image -> Object (x1,y1) (x0,y0) (u1,v1) s (u0,v0) (u3,v3) t (u2,v2) (x3,y3) (x2,y2)
Ancora… I passi da seguire per creare una texture sono i seguenti: - Generazione di un riferimento alla texture - Attivazione del riferimento - Settaggio dei parametri caratterizzanti la texture - Creazione della Texture mediante l'immagine
Generazione di un riferimento alla texture Si tratta di indicare ad OpenGL che vogliamo costruire una texture e vogliamo riservare spazio per memorizzare 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 attiva una delle texture create. OpenGL 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 operazione consiste nell’ 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.
Ancora… Per modificare dei parametri della texture utilizziamo la funzione: void glTexParameter{if}(GLenum target, GLenum pname, TYPE param); target è il tipo della texture(1D, 2D, 3D), pname è il parametro che vogliamo modificare, param e' il tipo di filtro da utilizzare . per modificare il Magnification filter pname sarà uguale a GL_TEXTURE_MAG_FILTER mentre per il Minification filter GL_TEXTURE_MIN_FILTER 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
Magnification filter e Minification filter Il Magnification filter entra in azione 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 texel rappresenta un aparte di pixel reali 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.
pname sarà uguale a GL_TEXTURE_ENV_MODE Ancora… Altri settaggi importanti sono le Texture Functions rappresentanti 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 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 Tale operazione indica ad OpenGL quale immagine vogliamo utilizzare per creare la nostra texture. La funzione per eseguire tale compito è: void glTexImage2D(GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); target deve essere uguale a GL_TEXTURE_2D; 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. La funzione per indicare le coordinate è semplicemente: void glTexCoord2{if}(TYPE coords);
Ancora… 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; 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
Argomenti Aggiuntivi…
Repeating e Clamping Può essere utile ripetere una determinata texture più volte all'interno dello stesso oggetto. Prendendo 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(GL_enum pname,GL_enum param) pname deve esser uguale a GL_TEXTURE_WRAP_S per la coordinata s e GL_TEXTURE_WRAP_T per la coordinata t, param può esser settato a 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. Oppure a GL_CLAMP e si riempie 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 textureNames è l'indirizzo degli identificativi delle texture da eliminare.
Mipmapping Per migliorare la qualità di visualizzazione delle texture quando queste si presentano più piccole dell’oggetto su cui si vogliono applicare è possibile crearne un certo numero 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