Texturování 9 – generování texturovacích souřadnic
Obsah
Manuální nastavení texturovacích souřadnicAutomatické generování texturovacích souřadnic
Mapování prostředí
Demonstrační příklady
Pokračování
Zkomprimovaný článek i s příklady pro modemisty
Manuální nastavení texturovacích souřadnic
Před vysvětlením techniky automatického generování texturovacích souřadnic si nejdříve zopakujme, jakým způsobem se texturovací souřadnice zadávají „manuálně“, tj. voláním funkcí OpenGL přímo z aplikace.
Při použití texturování je nutné ke každému vrcholu (vertexu) vykreslovaného polygonu zadat i jeho souřadnice v textuře. Jednorozměrná textura je přitom chápána jako jednorozměrné pole texelů, kde první texel má souřadnici [0.0] a poslední texel souřadnici [1.0]. Dvourozměrná textura představuje rastrovou pixmapu, kde texel v levém dolním rohu má souřadnici [0.0, 0.0] a texel v pravém horním rohu [1.0, 1.0]. U trojrozměrných textur je situace obdobná, pouze se přidává jedna dimenze pole.
K těmto souřadnicím se přidává ještě souřadnice čtvrtá, která má význam obdobný jako čtvrtá souřadnice při zadávání poloh jednotlivých vertexů v rovině či prostoru. To znamená, že po provedení veškerých transformací texturovacích souřadnic pomocí matice GL_TEXTURE je zajištěno, aby čtvrtá souřadnice byla rovna jedné.
Pro dodržení konzistence s dokumentací OpenGL budeme první souřadnici značit písmenem s, druhou písmenem t, třetí r a čtvrtou q.
Jak již víme z předchozích dílů, zadávají se souřadnice do textury pomocí příkazů:
void glTexCoord[1–4][sifd](souřadnice);
resp.
void glTexCoord[1–4][sifd]v(ukazatel na souřadnice);
Čísla 1, 2, 3 nebo 4 značí počet souřadnic, které voláním funkcí měníme. Pomocí písmen [sifd] se specifikuje datový typ každé souřadnice, tj. GLshort, GLint, GLfloat a GLdouble.
Výše uvedenými funkcemi je tedy možné zadat pro každý vertex jeho souřadnici v textuře, což však nemusí být vždy triviální úloha. Pro jednoduchá tělesa, jako je kvádr, kužel nebo válec, lze najít takové jednoznačné mapování z texturovacích souřadnic na souřadnice povrchu těles, aby nanášená textura nebyla zborcena. Pro jiné typy těles, jako je koule nebo tělesa s obecnou plochou, jednoznačné mapování nelze nalézt, proto je nanášená textura v těchto případech vždy zborcena (natahována nebo zkrácena).
Pomocí funkcí OpenGL můžeme automaticky mapovat texturu na prakticky libovolné těleso, vždy je však nutné mít na paměti, že může dojít (resp. u složitějších těles skoro vždy dojde) ke zborcení textury.
Automatické generování texturovacích souřadnic
V OpenGL lze místo manuálního generování texturovacích souřadnic použít automatické generování, které můžeme rozdělit na dvě části: buď je použito jednoduché lineární mapování, nebo se používá průmět textury nanesené na jednotkovou kouli. V tomto odstavci si popíšeme lineární mapování, druhá možnost je uvedena v následujícím odstavci.
Lineární automatické mapování texturovacích souřadnic pracuje na principu vyčíslení hodnoty výrazu:
coord_v=p1x0+p2y0+p3z0+p4w0
kde p1 až p4 jsou hodnoty zadané v dále popsané funkci void glTexGen*() a [x0, y0, z0, w0] jsou souřadnice vertexu, pro který se texturovací souřadnice počítají.
Pokud jsou hodnoty p1 až p4 normalizovány, je výsledkem předchozího výrazu vzdálenost vertexu od roviny reprezentované těmito hodnotami.
Výsledek coord_v může být spočítán pro každou texturovací souřadnici, tj. s, t, r nebo q.
Specifikace parametrů pro automatické lineární mapování se provádí pomocí funkcí:
glTexGeni(GLenum coord, GLenum pname, GLint param);
glTexGenf(GLenum coord, GLenum pname, GLfloat param);
glTexGend(GLenum coord, GLenum pname, GLdouble param);
glTexGeniv(GLenum coord, GLenum pname, GLint *param);
glTexGenfv(GLenum coord, GLenum pname, GLfloat *param);
glTexGendv(GLenum coord, GLenum pname, GLdouble *param);
Prvním argumentem těchto funkcí, tj. coord, se specifikuje jedna souřadnice do textury, jejíž parametry nastavujeme. Do tohoto argumentu lze zadávat hodnoty GL_S, GL_T, GL_R nebo GL_Q, které po řadě odpovídají souřadnicím s, t, r neboq.
Druhým argumentem pname specifikujeme, že v posledním argumentu jsou zadány způsoby generování texturovacích souřadnic (hodnota argumentu je rovna GL_TEXTURE_GEN_MODE) nebo parametry roviny, pomocí které se provádí výpočet souřadnice (hodnota argumentu je rovna GL_OBJECT_PLANE nebo GL_EYE_PLANE).
Třetí argument param má dva významy. Pokud byl argument pname nastaven na hodnotu GL_TEXTURE_GEN_MODE, je v tomto argumentu zadán způsob generování texturovacích souřadnic, který nabývá jedné z hodnot GL_OBJECT_LINEAR, GL_EYE_LINEAR nebo GL_SPHERE_MAP. Pokud však byl argument pname nastaven na hodnotu GL_OBJECT_PLANE nebo GL_EYE_PLANE, jsou v argumentu param uvedeny parametry roviny p1 ažp4.
Pokud tedy nastavíme lineární mapování, jsou texturovací souřadnice vypočteny pro každý vertex podle výše uvedené funkce. Toho lze využít například při vykreslování těles s konturami, tj. rovnoběžnými proužky. Tento způsob vykreslování se používá například v CAD systémech při zobrazování těles se složitě tvarovaným povrchem.
Při tvorbě kontur se mohou dokonce použít pouze jednorozměrné textury, u nichž se snižují nároky na pamět a současně se zrychluje výpočet texturovacích souřadnic. Funkce, která nastaví vykreslování těles s konturami rovnoběžnými se z-ovou rovinou, může vypadat následovně:
void setTextureParameters(void) { // rovina, vuci ktere se souracnice pocitaji GLfloat params[]={0.0, 0.0, 1.0, 0.0}; // nastaveni opakovani textury glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); // volba filtru pri zmene meritka glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // nahrani rastrovych dat do textury glPixelStorei( GL_UNPACK_ALIGNMENT, 1); glTexImage1D( GL_TEXTURE_1D, 0, 3, TEXTURE_WIDTH, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); // nastaveni rezimu textury glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // nastaveni mapovani texturovacich souradnic glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, params); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); }
Ve výše zobrazené funkci se nastavuje generování souřadnic do textury přímo podle polohy jednotlivých vertexů v prostoru. Výsledkem je textura, která je na těleso mapována bez ohledu na pozici pozorovatele vůči zobrazovanému tělesu.
Existuje však ještě jedna metoda výpočtu texturovacích souřadnic, která zohledňuje vzájemnou pozici vykreslovaného tělesa a pozorovatele. V této metodě se souřadnice do textury počítají podle upraveného vzorce:
coord_v=p1‚xe+p2‘ye+p3‚ze+p4‘we
ve kterém se veškeré výpočty provádějí v pohledových souřadnicích, tj. s polohou vertexu transformovanou do pohledových souřadnic a s rovinou transformovanou (násobenou) inverzní ModelView maticí.
Následuje ukázka funkce, pomocí které se nastaví výpočet souřadnice jednorozměrné textury v pohledových souřadnicích:
void setTextureParameters(void) { // rovina, vuci ktere se souracnice pocitaji GLfloat params[]={0.0, 0.0, 1.0, 0.0}; // nastaveni opakovani textury glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); // volba filtru pri zmene meritka glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // nahrani rastrovych dat do textury glPixelStorei( GL_UNPACK_ALIGNMENT, 1); glTexImage1D( GL_TEXTURE_1D, 0, 3, TEXTURE_WIDTH, 0, GL_RGB, GL_UNSIGNED_BYTE, texture); // nastaveni rezimu textury glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // nastaveni mapovani texturovacich souradnic glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); // zde je zmena glTexGenfv(GL_S, GL_EYE_PLANE, // a zde take params); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); }
Způsob výpočtu jednotlivých texturovacích souřadnic lze nastavovat nezávisle na sobě, tj. každá souřadnice může být vypočtena s pomocí jiné roviny.
Mapování prostředí
Existuje ještě jeden způsob, jakým lze automaticky vypočítat souřadnice do textury. Tento způsob se nazývá mapování (okolního) prostředí – environment mapping.
Při tomto způsobu výpočtu texturovacích souřadnic je vykreslované těleso jakoby obaleno koulí, na kterou je namapována textura. Tuto texturu lze získat například pomocí raytraceru s vhodně nastavenou kamerou typu „rybí oko“. Vlastní obrázek textury má v rastrovém obrázku tvar kruhu.
U každého vertexu musí být specifikována normála. Tato normála je chápána jako paprsek (polopřímka) vycházející z povrchu tělesa. Posléze je vypočten průsečík tohoto paprsku s koulí, na které je namapována textura. Podle souřadnic průsečíku na kouli je vyčíslena i souřadnice v textuře, protože mapování ze souřadnic na povrchu koule a souřadnic v rovině textury je jednoznačné.
Ukázka funkce, pomocí které se nastaví environment mapping:
void setTextureParameters(void)
{
// nastaveni opakovani textury
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S,
GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T,
GL_REPEAT);
// volba filtru pri zmene meritka
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER,
GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D,
GL_TEXTURE_MIN_FILTER,
GL_LINEAR);
// nahrani rastrovych dat do textury
glPixelStorei( GL_UNPACK_ALIGNMENT, 1);
glTexImage2D( GL_TEXTURE_2D, 0, 4,
TEXTURE_WIDTH, TEXTURE_HEIGHT,
0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
// nastaveni rezimu textury
glTexEnvi( GL_TEXTURE_ENV,
GL_TEXTURE_ENV_MODE,
GL_MODULATE);
// nastaveni mapovani texturovacich souradnic
glHint( GL_PERSPECTIVE_CORRECTION_HINT,
GL_NICEST);
// nastaveni environment mappingu
glTexGeni(GL_S, GL_SPHERE_MAP, 0);
glTexGeni(GL_T, GL_SPHERE_MAP, 0);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_2D);
}
Demonstrační příklady
První příklad (obarvená verze): vykreslení čajové konvičky s nanesenou dvourozměrnou texturou. U tohoto modelu jsou texturovací souřadnice explicitně zadány, stejně jako normály jednotlivých vertexů. Kromě texturování je vypočteno i osvětlení objektu, přičemž je použita modulace textur.
Obrázek 1: Screenshot z prvního demonstračního příkladu
Druhý příklad (obarvená verze): vykreslení čajové konvičky, na které jsou pomocí jednorozměrné textury vykresleny kontury. Výpočet texturovacích souřadnic je prováděn přímo z polohy vertexů.
Obrázek 2: Screenshot ze druhého demonstračního příkladu
Třetí příklad (obarvená verze): vykreslení čajové konvičky, na které jsou taktéž vykresleny kontury. V tomto případě se však výpočet texturovacích souřadnic provádí v pohledovém prostoru po transformaci vertexů maticí ModelView.
Obrázek 3: Screenshot ze třetího demonstračního příkladu
Čtvrtý příklad (obarvená verze): vykreslení čajové konvičky, na které je nanesena textura metodou environment mappingu. Při rotaci tělesa se tedy textura po povrchu tělesa přesouvá.
Obrázek 4: Screenshot ze čtvrtého demonstračního příkladu
Pátý příklad (obarvená verze): kombinace lineárního a sférického mapování (environment mappingu). Každá texturovací souřadnice je v tomto příkladě generována podle jiného vzorce.
Obrázek 5: Screenshot z pátého demonstračního příkladu
Pokračování
V dalším pokračování si popíšeme vztah mezi vykreslovacím řetězcem a framebufferem. Také si vysvětlíme princip práce stencil bufferu a accumulation bufferu.
Zkomprimovaný článek i s příklady pro modemisty
Pro majitele pomalejšího připojení k internetu je zde k dispozici celý článek i s přílohami zabalený do jednoho zip souboru.