Textur
Børre Stenseth
Forklaring av>Teksturer

Teksturer

Hva
self
Hvordan bruke teksturer, bitmaps, på overflater

OpenGL har kommandoer for å legge tekstur på overflater og for å vise fram bitmaps uten at disse er koplet til en overflate. Denne modulen vil ta for seg de grunnleggende mekanismene som er involvert og vil introdusere verktøy for å konvertere Windows bitmaps til et format som OpenGL kan handtere.

Det er rimelig greitt å tenke seg at en bitmap eller en tekstur kan legges på en overflate så og si som et teppe. Et praktisk brukbart verktøy må kunne handtere litt mer avanserte problemer.

Vi må kunne:

  • ta deler av en bitmap og legge på en flate.
  • strekke en bitmap og krympe en bitmap slik at den passer til flaten.
  • gjenta en bitmap flere ganger på en flate.
  • legge en bitmap på en overflate som ikke er plan
  • ta inn fra fil rimelig standard bildeformater som kan tjene som bitmaps

Vi ser litt på disse problemene i denne modulen.

Tekstur

Å bruke teksturer i OpenGL er ifølge Mark Kilgard, i boka: OpenGL Programming for the X window System, en operasjon i 4 steg:

  1. Skru på (enable) teksturer
          glEnable(GL_TEXTURE_2D);
          
  2. Spesifisere teksturen
          glTexImage2D(...);
          
  3. Spesifisere hvordan teksturen skal legges på overflaten
          glTexEnvi(...);
          
  4. Tegne ut ved å oppgi både geometriske koordinater på overflaten og teksturkoordinater
          glBegin(GL_TRIANGLES);
            glTexCoord(...); glVertex3f(..)
            glTexCoord(...); glVertex3f(..)
            glTexCoord(...); glVertex3f(..)
          glEnd();
          

Spesifikasjon av teksturer

Det finnes en rekke funksjoner og parametre for å styre utleggingen av teksturer på ulike geometriske former, og det finnes en rekke muligheter for å kombinere teksturer med bakgrunnsfarge. Det er ikke ambisjonene her å gå gjennom alle mulige kombinajoner og effektene av dem. Vi vil konsentrere oss om de viktigste prinsippene. Full kontroll over teksturer og effekter er et typisk tema for prøving og feiling på basis av OpenGL-dokumenstasjonen.

Når det gjelder å skru på tekstur, glEnable(), og å opprette teksturer, glTexImage2D(), så er det greitt å forstå dette fra OpenGL-dokumentasjonen, og vi går ikke nærmere inn på dette her.

La oss se litt nærmere på spesifikasjon av hvordan teksturen skal legges ut.

Merk at beskrivelsen nedenfor må betraktes som en første iterasjon av forståelse. Mulighetene er langt fler enn de som er beskrevet nedenfor.

Viktige rutiner er:

  glTexParameteri(GL_TEXTURE_2D,...,...);
  glTexEnvi(GL_TEXTURE_ENV,...,...);

glTexParameter

Det er spesielt to egenskaper vi kan styre ved hjelp av glTexParameteri():

  • Bestemmelse av hvorvidt teksturen skal låses til geometrien (clamp) eller om teksturen skal gjentas over flaten (repeat).

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
          

    Merk at GL_TEXTURE_WRAP_S angir en retning i teksturen. Alternativet i en 2D tekstur er GL_TEXTURE_WRAP_T.

  • Bestemme hvordan en pixel skal rendres dersom et teksturelement dekker mindre enn, eller mer enn en pixel.

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
          

    der et alternativ til GL_NEAREST er GL_LINEAR. Merk at ved glTexParameter kan vi altså også kontrollere vilken mipmap vi ønsker å bruke. Mipmaps er alternative teksturer som kan brukes når vi trenger mer eller mindre detaljrikdom, f.eks. basert på avstand.

glTexEnv

Ved hjelp av glTexEnvi() kan vi kontrollere hvordan teksturen skal forholde seg til den bakgrunnen den legges på.

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL)

legger normalt teksturen på uten å ta hensyn til bakgrunnsmaterialet.

Alternativene:

glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE)
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_BLEND)

har effekter som er detaljert beskrevet i openGL-dokumentasjonen. Hensikten er å muliggjøre påvirkning fra bakgrunnen på teksturen (eller omvendt).

Geometri

La oss først se på noen enkle mekanismer for å styre ut en tekstur på et rektangel. Vi har følgende utgangspunkt:

tekrek

Merk at når vi angir størrelsen på teksturmappen til å være 1 i begge retninger, så har ikke det noe med antall bildelementer (pixler i bitmapen) å gjøre. Vi sier pr definisjon at bitmapen som beskriver teksturen har denne dimensjonen. Den aktuelle bitmapen som i dette tilfellet er en .bmp fil er 64 x 64 pixler stor. Dimensjonene på rektangelet bestemmer vi helt fritt.

Merk at OpenGL vil kun ha bitmaps som er 2n x 2m store. n trenger ikke være lik m.

La oss betrakte noen tegninger og koden for å framstille dem. Vi fokuserer bare på geometrien.

towers

  • Bilde 1 er framstilt slik:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    ....
    
    glTexImage2D(..);
    glBegin(GL_POLYGON);
      glTexCoord2f(0.0f,0.0f);
      glVertex3f(-6.5f,-6.5f,0.1f);
    
      glTexCoord2f(1.0f,0.0f);
      glVertex3f(6.5f,-6.5f,0.1f);
    
      glTexCoord2f(1.0f,1.0f);
      glVertex3f(6.5f,6.5f,0.1f);
    
      glTexCoord2f(0.0f,1.0f);
      glVertex3f(-6.5f,6.5f,0.1f);
    glEnd();
    
  • Bilde 2 er framstilt slik:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
    ....
    
    glTexImage2D(..);
    glBegin(GL_POLYGON);
      glTexCoord2f(0.0f,0.0f);
      glVertex3f(-6.5f,-6.5f,0.1f);
    
      glTexCoord2f(3.0f,0.0f);
      glVertex3f(6.5f,-6.5f,0.1f);
    
      glTexCoord2f(3.0f,3.0f);
      glVertex3f(6.5f,6.5f,0.1f);
    
      glTexCoord2f(0.0f,3.0f);
      glVertex3f(-6.5f,6.5f,0.1f);
    glEnd();
    
  • Den eneste endringen mellom framstillingen av bilde 2 og bilde 3 er den første linja:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
      ...
    
  • I bilde 4 er de to første linjene:
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
      ....
    

Vi ser altså at vi kan kople hjørner i geometrien, glVertex3f(), med koordinater i teksturen, glTexCoord2f(). Dette er greitt så lenge vi kan "håndkode" scenen med kontropll over alle hjørner. Det bli verre når vi vil bruke Bezier-flater og OpenGLs funskjonsbibliotek for dette.

Det finnes en løsning på dette som er utformet slik at vi kan lage en mapping av teksturen på samme måte som vi mapper geometrien. Koden nedenfor legger ut en tekstur på en Bezierflate:

btower

...
// define ctrlpoints for beziersuface
GLfloat ctrlpoints[4][4][3] = // [v][u][xyz]
{
...
};
...
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

glEnable(GL_TEXTURE_2D);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_1);
glEnable(GL_MAP2_TEXTURE_COORD_2);

glTexImage2D(GL_TEXTURE_2D,0,3,
            m_theImage.GetWidth(),
            m_theImage.GetHeight(),
            0,GL_RGB,GL_UNSIGNED_BYTE,
            m_theImage.GetBitsPtr());

// map geometri
glMap2f(GL_MAP2_VERTEX_3,
        0.0f,1.0f,3,4,0.0f,1.0f,12,4,
        & ctrlpoints[0][0][0]);

// map texture
GLfloat txpts[2][2][2]={{{0.0, 0.0}, {1.0, 0.0}},
                       {{0.0, 1.0}, {1.0, 1.0}}};
glMap2f(GL_MAP2_TEXTURE_COORD_2,0,1,2,2,0,1,4,2,
        & txpts[0][0][0]);

glMapGrid2f(20,0.0f,1.0f,20,0.0f, 1.0f);

glEvalMesh2(GL_FILL, 0, 20, 0, 20);
Referanser
  1. DevIlDenton Woods,Nicolas Weber,Meloni DariosourceforgeA full featured cross-platform image libraryopenil.sourceforge.net/14-04-2010
  1. The OpenGL Programming Guide, 6 editionDave Schreiner, Mason Woo,Jackie Neider,Tom Davies2007Addison-Wesley Professional0321481003www.opengl.org/documentation/red_book/14-03-2010
  • Program som legger tekstur på alle sidene på en kloss:Boks med tekstur
  • Program som legger tekstur på en Bezier flate: Bezier med tekstur
  • Visual C++-programmet textur txtur.zip(VC++/gml) eller txtur.zip(VC++/.Net) demonstrerer mekanismene ovenfor samt teksturer på sylinder, kuler, disker og på en kloss.
Vedlikehold
B Stenseth, oppdatert mars 2010
(Velkommen) Forklaring av>Teksturer ((V)C)