|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
[OPENGL] Texture mapping
ho qualche problemino col mappare le coordinate 2d delle texture con le coordinate 3d di un vertice
ho provato a creare un triangolo in (10,10,-50) (20,10,-50) (20,20,-50) e a spiaccicargli una texture di un muro marrone fatto di mattoni. la texture è una bitmap a 24 bit,di 80 x 40 pixel,e quando la applico al triangolo viene fuori una schifezza. la mappature è questa,in ordine vertice (10,10,-50) coordinata texture (0,0) vertice (20,10,-50) coordinata texture (1,0) vertice (20,20,-50) coordinata texture (1,1) la modalità texture è settata su GL_REPLACE,cioè ho chiamato glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); e il risultato è una schifezza,viene fuori metà triangolo verde e metà marrone,neanche lo stesso marrone dell'immagine originale ho sbagliato qualcosa o forse è a causa del triangolo che è troppo piccolo? Ultima modifica di GordonFreeman : 02-12-2005 alle 23:55. |
|
|
|
|
|
#2 |
|
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
hum, siccome se ricordo bene le coordinate che mappano i vertici sulla texture si esprimevano da 0 a 1 penso proprio che quelli che dici di aver fatto è corretto; ci hai dato poche informazioni, posta qualche pezzo di codice
|
|
|
|
|
|
#3 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
[IMG]
Quote:
comunque grazie per la tua preziosa disponibilità,mi sembra che non sia la prima volta che mi aiuti Ultima modifica di GordonFreeman : 03-12-2005 alle 00:01. |
|
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
niente,non ho combinato
allora,il codice è il seguente,e allego anche la texture originale ed una foto del risultato (schifoso Codice:
// settaggi iniziali dei parametri di shading,lighting,textur mapping,etc.
void SetupRC(){
glShadeModel(GL_SMOOTH);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glEnable(GL_LIGHTING);
glFrontFace(GL_CCW);
float ambient[] = {0.3f,0.3f,0.3f,1.0f};
float diffuse[] = {0.7f,0.7f,0.7f,1.0f};
float position[] = {10.0f,10.0f,-45.0f,1.0f};
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
glMateriali(GL_FRONT,GL_SHININESS,128);
glEnable(GL_NORMALIZE);
glDisable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); /* Force 4 -byte alignment */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
BYTE bmp[80 * 40 * 3];
HBITMAP hbm = (HBITMAP)LoadImage(NULL,"texture.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
GetBitmapBits(hbm,sizeof(bmp),bmp);
for(int i = 0;i < 40;i++)
for(int j = 0;j < 80;j += 3){
BYTE temp = bmp[i * 80 * 3 + j];
bmp[i * 80 * 3 + j] = bmp[i * 80 * 3 + j + 2];
bmp[i * 80 * 3 + j + 2] = temp;
}
DeleteObject(hbm);
glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp);
}
// funzione di rendering,c'è solo la parte riguardante il posizionamento vertici
void RenderScene(){
// ...
glBindTexture(GL_TEXTURE_2D, 0);
glBegin(GL_TRIANGLES);
glTexCoord2f(0,0);
glVertex3f(10,10,-50);
glTexCoord2f(0,1);
glVertex3fv(20,10,-50);
glTexCoord2f(1,0);
glVertex3fv(20,20,-50);
glEnd();
// ..
}
Ultima modifica di GordonFreeman : 03-12-2005 alle 01:29. |
|
|
|
|
|
#5 |
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Ho dato un'occhiata molto veloce al codice, quindi prendi il tutto con le molle... =))
Secondo me sbagli qualcosa quando "crei" la texture, infatti ho provato a creare una texture a mano e pare funzionare. Per la precisione, se al posto di : glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp); Uso: BYTE bmp2[64 * 32 * 3]; for(int i = 0;i < 32;i++) for(int j = 0;j < 64;j++) { bmp2[i * 64 * 3 + j*3] = 250; bmp2[i * 64 * 3 + j*3+1] = 250; bmp2[i * 64 * 3 + j*3+2] = 250; } for(int i = 2;i < 30;i++) for(int j = 2;j < 62;j++) { bmp2[i * 64 * 3 + j*3] = 200; bmp2[i * 64 * 3 + j*3+1] = 20; bmp2[i * 64 * 3 + j*3+2] = 40; } glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp2); Pare funzionare appunto. Qualche nota comunque... Crei una texture di 80x40 (BYTE bmp[80 * 40 * 3]) poi pero' a glTexImage2D passi quella locazione di memoria facendogli credere che e' una texture 64x32 (glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp)). Dubito venga interpretata in modo corretto =) Il ciclo seguente non mi convince, j varia da 0 a 78, quindi non fai la completa scansione dell'immagine dato che una riga occupa 240 byte (se era quello che volevi fare). for(int i = 0;i < 40;i++) for(int j = 0;j < 80;j += 3){ BYTE temp = bmp[i * 80 * 3 + j]; bmp[i * 80 * 3 + j] = bmp[i * 80 * 3 + j + 2]; bmp[i * 80 * 3 + j + 2] = temp; } Infine, attento a come applichi le texture, ad esempio per il primo triangolo risulta; glBegin(GL_TRIANGLES); glTexCoord2f(0,0); glVertex3f(-10, 10, -50); glTexCoord2f(0,1); glVertex3f(10, 10, -50); glTexCoord2f(1,0); glVertex3f(10, 15, -50); glEnd(); Ma forse intendevi: glBegin(GL_TRIANGLES); glTexCoord2f(0, 0); glVertex3f(-10, 10, -50); glTexCoord2f(1,0); glVertex3f(10, 10, -50); glTexCoord2f(1,1); glVertex3f(10, 15, -50); glEnd(); Spero di non averti incasinato ancora di piu' le idee... =) Ultima modifica di Bane : 03-12-2005 alle 18:30. |
|
|
|
|
|
#6 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
Quote:
ok per capire quale di quelli che hai menzionato era il vero errore,provo a correggerne uno solo alla volta,a turno comunque,giusto per curiosità,se carico modelli dai file .3ds (3D Studio Max), essi specificano texture e texture mapping che non diano di questi problemi? quindi a me basta solo leggere ,così come sono specificati,i texels,le dimensioni della texture,e il mapping che ha con un certo triangolo? e se ci fossero problemi è colpa di 3d studio max,o no? p.s. guarda che j varia da 0 a 77 j + 0 j + 2 e li scambio quindi la scansione va da 0 a 79,è giusto |
|
|
|
|
|
|
#7 | |||
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Quote:
Ho scritto di fretta e con la febbre (anzi, ho risposto proprio perche' chiuso in casa e annoiato a morte =)) e potrei quindi aver incasinato qualche passaggio... =)) Quote:
Comunque in generale, si'... tu leggi il modello convertito nel formato XYZ che preferisci (o che devi, o che sai laggere, ecc. =)) ed hai tutto bello pronto... =) Quote:
J = 0; J = 3; J = 6; . . . J = 78; No? Ma non e' quello il punto... =) Quello che intendevo era un'altra cosa. Tu vuoi scambiare le componenti di ciascun pixel, quindi devi necessariamente fare una scansione di tutta l'immagine. Il ciclo che usi e': for(int i = 0; i < 40; i++) for(int j = 0; j < 80; j += 3) Gli indici utilizzati sono: i * 80 * 3 + j (eventualmente +2 per lo swap) Quali sono gli indici a cui si accede con questo ciclo? i = 0 -> 0 + (0, 3, 6, 9, ..., 78) -> (0, 3, 6, 9, ..., 78) i = 1 -> 240 + (0, 3, 6, 9, ..., 78) -> (240, 243, 246, 249, ..., 318) E gli indici fra 78 e 240? Ovviamente i buchi si ripetono per ogni i. Ultima modifica di Bane : 03-12-2005 alle 23:16. |
|||
|
|
|
|
|
#8 |
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Ah, fra l'altro temo che un pixel della bmp letta occupi 4 byte, non 3, quindi devi tenerne conto.
Comunque, ormai son qui, ho buttato un'occhiata piu' dettagliata... =) Giusto per darti un'idea della cosa, sosituisci: BYTE bmp[80 * 40 * 3]; HBITMAP hbm = (HBITMAP)LoadImage(NULL,"texture.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); GetBitmapBits(hbm,sizeof(bmp),bmp); for(int i = 0;i < 40;i++) for(int j = 0;j < 80;j += 3){ BYTE temp = bmp[i * 80 * 3 + j]; bmp[i * 80 * 3 + j] = bmp[i * 80 * 3 + j + 2]; bmp[i * 80 * 3 + j + 2] = temp; } DeleteObject(hbm); glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp); con: BYTE bmp[80 * 40 * 4]; HBITMAP hbm = (HBITMAP)LoadImage(NULL,"texture.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); long copyb = GetBitmapBits(hbm,sizeof(bmp),bmp); BYTE bmp2[64 * 32 * 3]; for(int i = 0;i < 32;i++) for(int j = 0;j < 64;j++){ bmp2[i * 64 * 3 + j*3] = bmp[i * 80 * 4 + j*4+2]; bmp2[i * 64 * 3 + j*3+1] = bmp[i * 80 * 4 + j*4+1]; bmp2[i * 64 * 3 + j*3+2] = bmp[i * 80 * 4 + j*4]; } DeleteObject(hbm); glTexImage2D(GL_TEXTURE_2D,0,3,64,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp2); Chiaramente la bmp originale viene tagliata brutalmente alla dimensione 64x32, ma dovresti gia' vedere qualcosa =) Poi dovresti sistemare le coordinate delle texture, perche' ovviamente vengono un po' sballate =) |
|
|
|
|
|
#9 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
Quote:
^_^ grazie |
|
|
|
|
|
|
#10 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
Quote:
comunque ho risolto ragazzi sentite questa : l'errore era in GetBitmapBits(),perchè ho provato a stampare su un file il contenuto dell'array bmp[],e i pixel erano apparentemente casuali!! infatti ho fatto il test con una bitmap creata a mano con paint,e aveva lo sfondo amaranto (R,G,B) = (128,0,0) in mezzo una linea orizzontale gialla (255,255,0) in mezzo una linea verticale color verde (0,255,0) cioè due linee in croce color giallo e verde,su sfondo amaranto ma dopo GetBitmapBits() in bmp[] c'erano dei pixel che non c'entravano un tubo,con dei colori a casaccio,tipo (104,64,56)... poi ho provato a leggere il file con fopen() + fseek() + fread() e così risulta tutto corretto Codice:
BYTE bmp[32 * 32 * 3];
FILE * fbmp = fopen("texture32x32 bricks.bmp","rb"); // oppure con texture32x32 custom.bmp
fseek(fbmp,sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER),SEEK_SET);
fread(bmp,sizeof(bmp),1,fbmp);
fclose(fbmp);
for(int i = 0;i < 32;i++)
for(int j = 0;j < 32;j++){
BYTE temp = bmp[i * 32 * 3 + j * 3];
bmp[i * 32 * 3 + j * 3] = bmp[i * 32 * 3 + j * 3 + 2];
bmp[i * 32 * 3 + j * 3 + 2] = temp;
}
glTexImage2D(GL_TEXTURE_2D,0,3,32,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp);
infatti ho provato a fare una cosa: ho creato un programma che prende la bitmap che ho creato a mano,la legge in un buffer con GetBitmapBits() e poi la stampa in un file con fprintf (cioè i valori dei pixel in formato testo),e leggendo tale file di log ho notato che i pixel risultano apparentemente casuali,come ho detto (la bitmap è stata aperta con LoadImage(),quindi una funzione per DDB,e non DIB,forse questo è rilevante) poi ho scritto un altro programma in cui c'è un array di byte statico,con i valori dei pixel che ho stampato prima,cioè ho copiato e incollato tutto in una dichiarazione di array di byte poi ho creato una bitmap "vuota" con CreateBitmapIndirect() e ho settato i suoi pixel con SetBitmapBits(),passandogli l'array di pixel citato sopra infine ho visualizzato la bitmap sulla finestra con StretchBlt() e il risultato è corretto!! ma quindi è come dico io,GetBitmapBits() è compatibile solo con GDI e non con OpenGL e forse nemmeno Direct3D (o Direct Graphics) in allegato il sorgente e le texture Ultima modifica di GordonFreeman : 04-12-2005 alle 22:39. |
|
|
|
|
|
|
#11 | ||
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Quote:
Quote:
Nel caso in esame: BYTE bmp[32 * 32 * 4]; HBITMAP hbm = (HBITMAP)LoadImage(NULL,"texture32x32 bricks.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); long copyb = GetBitmapBits(hbm,sizeof(bmp),bmp); BYTE bmp2[32 * 32 * 3]; for(int i = 0;i < 32;i++) for(int j = 0;j < 32;j++){ bmp2[i * 32 * 3 + j*3] = bmp[i * 32 * 4 + j*4+2]; bmp2[i * 32 * 3 + j*3+1] = bmp[i * 32 * 4 + j*4+1]; bmp2[i * 32 * 3 + j*3+2] = bmp[i * 32 * 4 + j*4]; } DeleteObject(hbm); glTexImage2D(GL_TEXTURE_2D,0,3,32,32,0,GL_RGB,GL_UNSIGNED_BYTE,bmp2); E la texture viene caricata in modo corretto. Vabbeh, hai risolto comunque... =)) |
||
|
|
|
|
|
#12 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
Quote:
allora,intanto ti dimostro che sono 3 byte per pixel,infatti le due texture in allegato sopra sono di 3.1 KB,cioè 3072 byte + headers formato bitmap,cioè 32 * 32 * 3 + headers,e non 32 * 32 * 4 + headers = 4096 byte + headers = 4.1 KB e mi sa che vale per qualunque bitmap a 24 bit poi perchè pensavi ai 4 byte? forse se fosse una bitmap a 32 bit,cioè RGBA edit : aaaah aspetta,forse vuoi dire che GetBitmapBits() aggiunge i valori alpha ai pixel RGB per allineare la dimensione di ogni riga a un multiplo di 4 byte?? Ultima modifica di GordonFreeman : 04-12-2005 alle 23:52. |
|
|
|
|
|
|
#13 | |
|
Member
Iscritto dal: Aug 2003
Messaggi: 125
|
Quote:
O "GetBitmapBits" o "LoadImage". Tu non devi pensare a come e' fatta la bmp originale, ma a come viene caricata da "LoadImage" e/o "convertita" da "GetBitmapBits"... =) |
|
|
|
|
|
|
#14 | |
|
Member
Iscritto dal: Apr 2005
Messaggi: 296
|
Quote:
Codice:
BITMAP bm; GetObject(hBitmap,sizeof(bm),&bm); // hBitmap aperta con LoadImage // bm.bmWidthBytes = dimensione di una riga,in byte,multiplo di 4 // bm.bmBitsPixel = bits per pixel ma sinceramente chissenefrega,basta sapere a tempo di compilazione che tipo di bitmap si stanno caricando come texture,e poi usare fopen() + fseek() + fread() p.s. ah no,non sarà stato per allineare a 4 byte,ma perchè Windows converte tutto in RGBA forse....boh,ma chi se ne frega Ultima modifica di GordonFreeman : 05-12-2005 alle 00:27. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:32.



















