INFORMATICA GRAFICA SSD INGINF05 Sistemi di elaborazione delle
INFORMATICA GRAFICA – SSD ING-INF/05 Sistemi di elaborazione delle informazioni a. a. 2006/2007 LEZIONE PRATICA Open. GL Graphics Texture Mapping
Texture Mapping La “texture mapping” permette di migliorare il realismo della scena senza incrementare il numero di primitive geometriche Le textures sono come una “pelle” che avvolgono le superfici Il piu’ delle volte vengono utilizzate texture 2 D. Ma esistono anche texture 1 D e 3 D.
Texture Format In Open. GL le textures internamente in memoria devono essere salvate in formato raw RGB: {RGB}, {RGB}… E’ possibile specificare le texture direttamente nel codice o usare files esterni. Es PPM e’ un formato grafico perfetto per I nostri scopi. Infatti sono particolarmente semplici da trattare Ad esempio per creare una scacchiera 4 x 4 : --------------------------P 3 ASCII format 4 4 255 255 255 255 0 0 0 0 0 0 255 255 255 ---------------------------
Basic Idea of Mapping Le texture 2 D vivono nello spazio 2 D I punti sono parametrizzati nelle coordinate 2 D (s, t) E’ necessario definire il mapping dalle coordinate mondo 3 D (x, y, z) alle coordinate texture 2 D (s, t) == Per trovare il colore nella texture, prendi un punto (x, y, z) sulla superfice, mappalo in spazio texture e usa I colori nella look-up table delle texture Es con I Polygoni Open. GL: Specifica le coordinate (s, t) per ogni vertice del poligono Open. GL interpola (s, t) per ogni altro punto del poligono automaticamente
Texture Interpolation Il mapping e’ un generale espresso tramite due funzioni che hanno come parametri le coordinate mondo: s = s (x, y, z) t = t (x, y, z) t s Texture map NOTA: linee dritte nello spazio mondo sono mappate in linee dritte nello spazio texture Triangle in world space
Interpolating Coordinates
Curved Surface Texture Coordinates Esempio complesso. Abbiamo uno superfice parametrica S = {x(u, v), y(u, v), z(u, v)} approssimata da una mesh poligonale Come trovare il mapping delle coordinate nello spazio texture?
Cylindrical Surfaces Parametric form Mapping function Esempio, se voglio mappare tutto il cilindro: [0, 2 PI]x[0, 1] S=(Teta-0)/(2 PI-0) T=(h-0)/(1 -0)
Spherical Surfaces Parametric form Linear Mapping Esempio, se voglio mappare tutta la cilindro: [ 0, 2 PI ] x [ -PI/2 , PI/2 ] S = (Teta-0) / (2 PI-0)=Teta/2 PI T = (h+PI/2) / (PI/2+PI/2)=0. 5+h/PI
2 D Texturing Come abilitare il 2 D Texturing: gl. Enable(GL_TEXTURE_2 D) Come definire una texture 2 D gl. Tex. Image 2 D(GL_TEXTURE_2 D, level, components, width, height, border, format, type, texels) Level Components width, height Border Format Type Textels number of the texture resolutions. For now = 0 number of color components. (ex. 3 for RGB) size of the texture map with (1) or without (0) border format of the texture data, e. g. GL_RGB data type of the texture data, e. g. GL_BYTE pointer to the actual texture image data
2 D Texturing Texture objects memorizzano I dati delle texture in modo che possano essere utilizzate in ogni. Open. GL supporta piu’ texture objects. Prima di tutto generare la texture map: gl. Gen. Textures(num, texture. Names) num the number of texture objects identifiers to generate texture. Names int array holding identifiers Specificare che si vuole utilizzare, da adesso in poi, un certo texture object gl. Bind. Texture(target, identifier) Target can be GL_TEXTURE_1 D, GL_TEXTURE_2 D, or GL_TEXTURE 3 D Identifier a texture object identifier Es Se si vogliono usare “n” textures: gl. Gen. Textures(n, array); gl. Bind. Texture(GL_TEXTURE_2 D, array[0]); gl. Tex. Image 2 d(…); gl. Bind. Texture(GL_TEXTURE_2 D, array[1]); gl. Tex. Image 2 d(…); … Nel GLUT redraw callback: gl. Bind. Texture(GL_TEXTURE_2 D, array[0]); …
Texture Coordinates • Ogni punto della superfice deve avere quindi delle coordinate texture (s, t) • Specifichiamo le texture coordinates solo per I vertici del poligono. Open. GL interpolerà I restanti punti interni. • Si usa la gl. Tex. Coord 2 f(s, t) per settare le coordinate texture. Es: • gl. Tex. Coord 2 f(0. 5 f, 0. 5 f); • gl. Vertex 3 f(x, y, z);
1 D and 3 D Textures • 1 D textures possono essere considerate come texture 2 D con altezza pari a 1. gl. Tex. Image 1 D(GL_TEXTURE_1 D, level, components, width, border, format, type, texels) • 3 D textures possono essere considerate come stack di 2 D textures. Sono spesso utilizzate per il medical imaging: gl. Tex. Image 3 D(GL_TEXTURE_3 D, level, components, width, height, depth, border, format, type, texels)
3 D Texturing Examples
Texture Filtering gl. Tex. Parameteri(GL_TEXTURE_2 D, pname, param) Specifica “COME” applicare una texture • Es Un pixel puo’ corrispondere ad una frazione di un solo texel o ad un insieme di texel nella texture map. – Magnification: un pixel meno di un texel gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_MAG_FILTER, type); Es prendi il texel piu’ vicino NEAREST O fai interpolazione dei texel or GL_LINEAR – Minification: un pixel piu’ di un texel gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_MIN_FILTER, type); Es fai interpolazione dei texel che occupa GL_LINEAR
Texture Filtering
Texture Functions gl. Tex. Envi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode); Come I colori della texture map sono utilizzati per modificare I colori nel frame buffer mode: GL_DECAL GL_BLEND GL_MODULATE replace pixel color with texture color C = Cf(1 -Ct) + Cc. Ct, Cf is the pixel color, Ct is the texture color, Cc is some constant color C = Cf Ct Esempio: Se e’ attivo il lighting abbiamo bisogno che la texture appaia piu’ o meno chiara a seconda dell’illuminazione (1) Crea un poligono, accendi le luci e illuminaloy (2) gl. Tex. Envi(GL_TEXTURE_2 D, GL_TEXTURE_ENV_MODE, GL_MODULATE) (3) In questo modo il colore della texture e’ moltiplicato con il colore della superfice (con illuminazione) ed ho l’effetto voluto
Boundaries Le texture sono definite nel dominio (0, 0) -> (1, 1) domain. Cosa succede se un punto ha coordinate texture fuori questo dominio? Repeat. Le coordinate texture sono ripetute. gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_WRAP_S, GL_REPEAT) gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_WRAP_R, GL_REPEAT) Clamp to Edge. Le coordinate texture sono troncate ad un valore valido gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_WRAP_S, GL_CLAMP) gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_WRAP_R, GL_CLAMP) Border color. E’ possibile specificare un colore del bordo. gl. Tex. Parameterfv(GL_TEXTURE_2 D, GL_TEXTURE_BORDER_COLOR, R, G, B, A)
Repeat e Border Color
Clamp e Border Color
Only Border Color (1, 1) (0, 0)
Richiamo: viewing transformations (1) Posiziona la macchina fotografica (2) Piazzare il cavalletto (3) Punta la macchina fotografica Per navigare nella scena (fly through) si puo’ semplicemente usare: glu. Look. At( eyex, eyey, eyez, aimx, aimy, aimz, upx, upy, upz ) up vector determina l’orientamento
Richiamo: Projection Transformation gl. Frustum( left, right, bottom, top, z. Near, z. Far ) glu. Perspective( fovy, aspect, z. Near, z. Far )
Esempio: textures. c Posso sempre definire le textures staticamente /* Texture Dimensions */ int texwidth = 4, texheight = 4; /* Texture data */ unsigned char texdata[]= { 255, 255, 255, 0, 0, 0, }; 0, 0, 0, 255, 255, 255, 255
Esempio: textures. c static char *circles[] = int main(int argc, char **argv){ { […] ". . xxxx. . . . ", ". . xxxx. . . ", make. Floor. Texture(); ". xxxxx. . . ", ". xxx. . ", glut. Main. Loop(); "xxx. . ", return 0; "xxx. . . . ", } "xxx. . ", void make. Floor. Texture(void){ ". xxx. . ", ". xxxxx. . . ", GLubyte floor. Texture[16][3]; ". . xxxx. . . ", GLubyte *loc; ". . xxxx. . . . ", ". . . . ", int s, t; ". . . . ", loc = (GLubyte*) floor. Texture; ". . . . ", for (t = 0; t < 16; t++) { }; for (s = 0; s < 16; s++) { if (circles[t][s] == 'x') { loc[0] = 0 x 1 f; loc[1] = 0 x 8 f; loc[2] = 0 x 1 f; } else loc[0] = loc[1] = loc[2] =0 xaa; loc += 3; } } gl. Tex. Parameteri(GL_TEXTURE_2 D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl. Tex. Image 2 D(GL_TEXTURE_2 D, 0, 3, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, floor. Texture); } run
Esempio: textures. c static void redraw(void) { gl. Clear. Color(0, 0. 4, 1, 1); gl. Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl. Push. Matrix(); gl. Rotatef(anglex, 1. 0, 0. 0); gl. Rotatef(angley, 0. 0, 1. 0, 0. 0); gl. Color 3 f(1, 1, 1); gl. Enable(GL_TEXTURE_2 D); gl. Begin(GL_QUADS); gl. Tex. Coord 2 f( 0. 0, 0. 0); gl. Vertex 3 f(-1, 0); gl. Tex. Coord 2 f( 0. 0, 16. 0); gl. Vertex 3 f(+1, -1, 0); gl. Tex. Coord 2 f(16. 0, 16. 0); gl. Vertex 3 f(+1, 0); gl. Tex. Coord 2 f(16. 0, 0. 0); gl. Vertex 3 f(-1, +1, 0); gl. End(); gl. Disable(GL_TEXTURE_2 D); gl. Pop. Matrix(); glut. Swap. Buffers(); }
PPM conversion. Esempio: texture 2. c Per convertire un file generico in PPM: (1) Usare il programma xv in Linux/Mac. Os. X. Aprire il file da convertire (2) Cliccare il tasto destro e scegli “Save” (3) Seleziona PPM come formato (raw = P 6, ascii = P 3 better!) Da C questo e’ il codice per caricare il PPM: FILE *f; /* File pointer */ char temp[100]; /* to store a single line */ char img_type; /* Temporary Storage */ int texwidth, texheight; /* Texture Dimensions */ unsigned char *texdata; /* Texture data */ int val; run f=fopen("texture. ppm", "r"); /* Open the file */ do {fgets(temp, 100, f); } while (temp[0]=='#'); /* skip comments */
Esempio: texture 2. c img_type = temp[1]; /* Store the PPM type */ do {fgets(temp, 100, f); } while (temp[0]=='#'); /* skip comments */ sscanf(temp, "%d %d", &texwidth, &texheight); /* Store Dimensions */ do {fgets(temp, 100, f); } while (temp[0]=='#'); /* skip comments*/ texdata=(char*) malloc (sizeof(char)*texwidth*texheight*3); /* Read image */ if (img_type == '6') /* what kind? */ fread(texdata, sizeof(char)*3, texwidth*texheight, f); else if(img_type == '3') { --------------------------P 3 for(i=0; i<texwidth*texheight*3; i++) 44 fscanf(f, ”%d”, &val); texdata[i]=val; 255 255 0 0 0 } 255 255 255 0 0 0 fclose(f); /* Close File */ 000 000 255 255 255 --------------------------- 000 255
Esempio: texture 2. c static void redraw(void) { gl. Clear. Color(0, 0. 4 f, 1, 1); gl. Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl. Push. Matrix(); gl. Rotatef(anglex, 1. 0, 0. 0); gl. Rotatef(angley, 0. 0, 1. 0, 0. 0); gl. Color 3 f(1, 1, 1); gl. Enable( GL_TEXTURE_2 D ); gl. Begin(GL_QUADS); gl. Tex. Coord 2 f(0. 0, gl. Tex. Coord 2 f(1. 0, gl. End(); gl. Disable( GL_TEXTURE_2 D ); gl. Pop. Matrix(); glut. Swap. Buffers(); } 0. 0); gl. Vertex 3 f(-1, 0); 1. 0); gl. Vertex 3 f(+1, 0); 0. 0); gl. Vertex 3 f(-1, +1, 0);
Esempio : tessellation. c Tessellation: = per visualizzare poligoni non convessi o poligoni contententi buchi e’ necessario triangolare il poligono. Quindi suddivido il poligono in poligoni convessi. Questa operazione e’ detta tessellazione. GLU fornisce delle funziooni che effettuano la tesselation.
Esempio : tessellation. c 1. Alloca un nuovo oggetto GLU tessellation : GLUtesselator *tess = glu. New. Tess(); 2. Assigna I callback in relazione agli eventi: glu. Tess. Callback (tess, GLU_TESS_BEGIN , tcb. Begin); glu. Tess. Callback (tess, GLU_TESS_VERTEX, tcb. Vertex); glu. Tess. Callback (tess, GLU_TESS_END , tcb. End); 3. Se la primitiva geometrica e’ del tipo self-intersecting bisogna specificare un callback per la creazione dei nuovi vertici: glu. Tess. Callback (tess, GLU_TESS_COMBINE, tcb. Combine);
Esempio : tessellation. c Esempio: tesselation 4. Comunicare a GLU l’oggetto geometrico complesso: GLdouble data[num. Verts][3]; glu. Tess. Begin. Polygon (tess, NULL); for (i=0; i<sizeof(data)/(sizeof(GLdouble)*3); i++) glu. Tess. Vertex (tess, data[i]); glu. End. Polygon (tess); 5. Nel tuo callback chiava le apposite funzioni Open. GL: void tcb. Begin (GLenum prim) void tcb. Vertex (void *data) void tcb. End () { gl. Begin (prim); } { gl. Vertex 3 dv ((GLdouble *)data); } { gl. End (); }
Esempio : tessellation. c GLdouble body. Width = 3. 0; GLfloat body[][2] = { … }; (8, 6) GLfloat arm[][2] = { … }; GLfloat eye[][2] = { … }; (8, 4) (9, 3) (9, 2) static GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0. 5}, {9, 0}, {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} }; run
Esempio : tessellation. c int main(int argc, char **argv) { […] tobj = glu. New. Tess(); glu. Tess. Callback(tobj, GLU_BEGIN, gl. Begin); glu. Tess. Callback(tobj, GLU_VERTEX, gl. Vertex 2 fv); /* semi-tricky */ glu. Tess. Callback(tobj, GLU_END, gl. End); gl. Shade. Model(GL_FLAT); gl. Light. Modeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); gl. Lightfv(GL_LIGHT 0, GL_DIFFUSE, light. Color); gl. Enable(GL_LIGHT 0); gl. Enable(GL_LIGHTING); gl. Materialfv(GL_FRONT, GL_DIFFUSE, skin. Color); […] }
Esempio : tessellation. c void extrude(GLfloat data[][2], unsigned int data. Size, GLfloat thickness) { GLdouble vertex[3], dx, dy, len; int i; int numpoints = data. Size / (2 * sizeof(GLfloat)); Normale= y 1 -y 0 , -(x 1 -x 0) X 1, y 1 /* bordi che congiungono la faccia base e quella estrusa */ gl. Front. Face(GL_CW); X 0, y 0 gl. Begin( GL_QUAD_STRIP ); for (i = 0; i <= numpoints; i++) { Glfloat x = data[i % numpoints][0] , xnext =data[(i + 1) % numpoints][0]; Glfloat y = data[i % numpoints][1] , ynext = data[(i + 1) % numpoints][1]; gl. Vertex 3 f(x, y, 0. 0 ); gl. Vertex 3 f(x, y, thickness); z dx = ynext- y; dy = x-xnext; len = sqrt(dx * dx + dy * dy); gl. Normal 3 f(dx / len, dy / len, 0. 0); } gl. End(); y x
Esempio : tessellation. c /* faccia base non estrusa */ gl. Front. Face(GL_CW); gl. Normal 3 f(0. 0, -1. 0); glu. Begin. Polygon(tobj); for (i = 0; i < numpoints; i++) { vertex[0] = data[i][0]; vertex[1] = data[i][1]; vertex[2] = 0; glu. Tess. Vertex(tobj, vertex, data[i]); } glu. End. Polygon(tobj); /* faccia base estrusa di tickness */ gl. Push. Matrix(); gl. Translatef(0. 0, thickness); gl. Front. Face(GL_CCW); gl. Normal 3 f(0. 0, 1. 0); glu. Begin. Polygon (tobj); z for (i = 0; i < numpoints; i++) { vertex[0] = data[i][0]; vertex[1] = data[i][1]; vertex[2] = 0; glu. Tess. Vertex(tobj, vertex, data[i]); } glu. End. Polygon(tobj); gl. Pop. Matrix(); Se voglio risparmiare Una push matrix? y x
Esempio : tessellation. c static void redraw(void){ […] gl. Translatef(-6, -5, +body. Width / 2 -3); extrude( body , sizeof(body) , body. Width); gl. Translatef(0. 0, body. Width); extrude( arm , sizeof(arm) , body. Width / 4); extrude( leg , sizeof(leg) , body. Width / 2); gl. Translatef(0. 0, -body. Width - body. Width / 4); extrude( arm , sizeof(arm) , body. Width / 4); gl. Translatef(0. 0, -body. Width / 4); extrude( leg , sizeof(leg) , body. Width / 2); gl. Translatef(0. 0, body. Width / 2 - 0. 1); extrude( eye , sizeof(eye) , body. Width + 0. 2); […]
- Slides: 37