Obsah
1. Manipulace s rastrovými obrazy pro potřeby texturování a změny měřítka2. Změna měřítka bitmapy či pixmapy
3. Vytváření mipmap
4. Vytvoření jednorozměrné mipmapy
5. Demonstrační příklady
6. Obsah dalšího pokračování
7. Seznam funkcí OpenGL a GLUT zmíněných v této části
8. Nové funkce popsané v této části
9. Zkomprimovaná verze článku i s přílohami
1. Manipulace s rastrovými obrazy pro potřeby texturování a změny měřítka
Nadstavbová knihovna GLU obsahuje některé funkce, které je možné použít při mipmappingu, tj. při vytváření série bitmap či pixmap, z nichž každá má oproti předchozímu obrázku poloviční rozlišení jak v horizontální, tak i ve vertikální ose. Kromě toho jsou v této knihovně dostupné i funkce pro změnu měřítka bitmap a pixmap, jejichž použití však není omezeno pouze na texturování, ale lze pomocí nich měnit rozlišení rastrových obrázků na obrazovce. Všechny tyto funkce si popíšeme v dalším textu.
2. Změna měřítka bitmapy či pixmapy
Pomocí funkce gluScaleImage() je možné měnit rozlišení bitmapy (jednobarevného obrázku) či pixmapy (tj. barevného rastrového obrázku s volitelným alfa kanálem) na libovolnou hodnotu. Při rozbalování a balení pixmapy se korektně používají nastavené režimy rozbalování a balení pixelů – viz podrobný popis funkcí glPixelStorei() a glPixelStoref(), které byly popsány v seriálu o grafické knihovně OpenGL. Kromě toho je možné pomocí funkce gluScaleImage() měnit i datový typ uložených pixelů.
Pokud se provádí zmenšování obrázku, tj. rozlišení finálního (cílového) obrázku v obou osách je menší než rozlišení obrázku zdrojového, používá se filtr, který mixuje barvy více pixelů zdrojového obrázku do jednoho pixelu obrázku cílového. Vizuální výsledek je tedy mnohem lepší než při prostém přemapování pixelů, při němž dochází k velké ztrátě vizuálních informací.
Při zvětšování obrázku (tj. zvyšování rozlišení) se provádí bilineární interpolace, protože zdrojových pixelů je méně než pixelů ve finálním obrázku. Vizuální výsledek je opět lepší než při použití prostého mapování pixelů, protože se částečně rozmazávají hranice mezi původními pixely.
Funkce gluScaleImage(), pomocí níž se změna měřítka rastrového obrázku provádí, má následující hlavičku:
GLint gluScaleImage( GLenum format, GLint widthIn, GLint heightIn, GLenum typeIn, const void *dataIn, GLint widthOut, GLint heightOut, GLenum typeOut, void *dataOut );
Význam jednotlivých parametrů funkce gluScaleImage() je následující:
- V parametru format je uložen formát vstupního i výstupního obrázku, který je stejný jako při použití funkce glDrawPixels(), tj. je zde možné použít následující hodnoty:
GL_COLOR_INDEX (indexy do barevné palety),
GL_STENCIL_INDEX (indexy do paměti šablony),
GL_DEPTH_COMPONENT (hodnoty paměti hloubky),
GL_RED (červené barvové složky),
GL_GREEN (zelené barvové složky),
GL_BLUE (modré barvové složky),
GL_ALPHA (průhlednosti pixelů),
GL_RGB (barvový formát RGB),
GL_RGBA (barvový formát RGB s průhledností),
GL_BGR_EXT („obrácený“ formát RGB – prohozené barvové složky),
GL_BGRA_EXT („obrácený“ formát RGBA),
GL_LUMINANCE (světlosti pixelů) a
GL_LUMINANCE_ALPHA (světlosti a průhlednosti pixelů). - Ve druhém parametru widthIn je funkci gluScaleImage() předána šířka zdrojového obrázku, která je specifikována přímo v pixelech.
- Ve třetím parametru heightIn je předána výška obrázku, která je taktéž specifikována v pixelech.
- Hodnotou parametru typeIn se specifikuje datový typ, ve kterém jsou uloženy barvy či jiné informace o jednotlivých pixelech. Tento parametr má stejný význam jako parametr type ve funkci glDrawPixels(), tj.:
GL_UNSIGNED_BYTE (8bitový bezznaménkový integer),
GL_BYTE (8bitový integer),
GL_BITMAP (bity spojené do slov),
GL_UNSIGNED_SHORT (16bitový bezznaménkový integer),
GL_SHORT, (16bitový integer)
GL_UNSIGNED_INT, (32bitový bezznaménkový integer)
GL_INT (32bitový integer) nebo
GL_FLOAT (32bitový float dle normy IEEE). - Ukazatel na vlastní zdrojový obrázek, tj. na pole pixelů, se předává v parametru dataIn.
- Pomocí parametrů widthOut a heightOut je specifikována velikost výsledného obrázku. Je možné celý obrázek buď zvětšovat, zmenšovat, nebo ho dokonce v jednom směru roztáhnout a ve druhém stlačit.
- V parametru typeOut se předává datový typ pixelů ve výsledném obrázku – to mimo jiné znamená, že výsledný obrázek může být zkonvertován do jiné struktury, což se hodí zejména při práci s obrázky načtenými z externích souborů. Tento parametr může nabývat hodnot: GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, neboGL_FLOAT, podobně jako parametr typeIn.
- V posledním parametru dataOut je předán ukazatel na nově vznikající cílový obrázek, tj. na jeho jednotlivé pixely.
Pokud proběhne změna rozlišení rastrového obrázku korektně, vrací se návratová hodnota 0, v případě chyby se vrací chybový kód, který je od nuly odlišný. Převod chybového kódu na čitelný řetězec (s případným výpisem tohoto řetězce) se může provést pomocí funkcegluErrorString(). Většinou se vrací chybové kódy GLU_INVALID_ENUM, GLU_INVALID_VALUE nebo GLU_OUT_OF_MEMORY.
3. Vytváření mipmap
Další skupinou funkcí, kterou nabízí grafická nadstavbová knihovna GLU, jsou funkce pro vytváření takzvaných mipmap. Použitím mipmap jsem se zabýval již v seriálu o grafické knihovně OpenGL, zejména v části XXV (www.root.cz/clanek/1974), zde si pouze rychle zopakujme přednosti mipmap při texturování:
- odstranění vizuálních artefaktů při přibližování a vzdalování kamery od otexturovaného povrchu.
- zamezení poblikávání pixelů (vzniklé nanášením texelů na zobrazovaný povrch) při průchodu scénou.
- zlepšení náhledu na textury při velkém přiblížení nebo naopak vzdálení.
- hierarchická datová struktura, s jejíž pomocí je možné mipmapami velmi jednoduše procházet.
V dalších odstavcích a následujícím pokračování tohoto seriálu si funkce pro práci s mipmapami podrobně popíšeme.
4. Vytvoření jednorozměrné mipmapy
První popisovanou funkcí pro práci s mipmapami je funkce pro vytvoření jednorozměrné mipmapy. Vstupem této funkce je jednorozměrný rastrový obrázek, výstupem je mipmapa, na jejíž nejvyšší úrovni je zadaný obrázek o specifikovaném rozlišení a na úrovni nejnižší je pouze jeden pixel, který reprezentuje průměrnou barvu všech pixelů ve zdrojovém obrázku. Vytvoření všech úrovní mipmapy se provádí pomocí dříve popsané funkce gluScaleImage().
Funkce pro vytvoření jednorozměrné mipmapy se jmenuje gluBuild1DMipmaps() a má následující deklaraci:
GLint gluBuild1DMipmaps( GLenum target, GLint components, GLint width, GLenum format, GLenum type, void *data );
Význam jednotlivých parametrů funkce gluBuild1DMipmaps():
- V parametru target musí být předán typ cílové textury, která bude z mipmapy vytvářena. U této funkce musí být parametr target vždy nastaven na hodnotu GL_TEXTURE_1D, v opačném případě se funkce neprovede korektně a vrátí se chybový kód GLU_INVALID_ENUM.
- Parametrem components je možné specifikovat počet barvových komponent v textuře. Mezi podporované hodnoty patří: 1 (jedna barva, průhlednost nebo luminance), 2 (většinou luminance a průhlednost), 3 (RGB) nebo 4 (RGBA) barvové složky.
- V parametru width se zadává šířka obrázku, který je uložen na nejvyšší úrovni mipmapy. Tento údaj by měl být mocninou dvou, jinak se před vlastní konstrukcí mipmapy obrázek automaticky zvětší či zmenší na nejbližší hodnotu, která je mocninou dvou. Změna velikosti obrázku se provádí jednoduše – zavolá se výše popsaná funkce gluScaleImage().
- V parametru format se předává formát pixelů, tj. informace o tom, z jakých barvových složek může být barva pixelu vytvořena. Povolené hodnoty jsou:
GL_COLOR_INDEX (index do barvové palety),
GL_RED (pouze červená barvová složka),
GL_GREEN (pouze zelená barvová složka),
GL_BLUE (pouze modrá barvová složka),
GL_ALPHA (průhlednost),
GL_RGB (true color barvy),
GL_RGBA (true color barvy s průhledností),
GL_BGR_EXT (obrácený formát RGB),
GL_BGRA_EXT (obrácený formát RGBA),
GL_LUMINANCE (světlost) a
GL_LUMINANCE_ALPHA (světlost s průhledností). - Parametrem type se specifikuje datový typ jednotlivých barvových složek pixelů. Povolené hodnoty jsou stejné jako u funkce glDrawPixels() nebo u výše zmíněné funkce gluScaleImage(), tj. GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT,GL_SHORT, GL_UNSIGNED_INT, GL_INT nebo GL_FLOAT.
- V posledním parametru data je předán ukazatel na rastrová data obrázku, ze kterého se má vytvořit jednorozměrná mipmapa. Vlastní obrázek není vytvořením mipmapy nijak změněn.
Pokud proběhne vytvoření mipmapy bez chyby, vrací se hodnota 0, v případě výskytu chyby se vrací chybový kód, který je od nuly odlišný. Převod chybového kódu na čitelný řetězec (s případným výpisem tohoto řetězce) se může provést pomocí funkce gluErrorString(). Většinou se vrací chybové kódy GLU_INVALID_ENUM (špatně použité symbolické konstanty), GLU_INVALID_VALUE (nekorektní hodnoty parametrů) nebo GLU_OUT_OF_MEMORY (nedostatek paměti pro vytvoření mipmapy).
Po vytvoření mipmapy je pro každou její úroveň zavolána funkce glTexImage1D(), takže uživatel již toto volání nemusí v aplikaci explicitně provádět.
Funkce pro vytvoření dvojrozměrné a trojrozměrné mipmapy budou uvedeny v následujícím pokračování tohoto seriálu.
5. Demonstrační příklady
Po překladu a spuštění prvního demonstračního příkladu se zobrazí model tělesa, který je pokrytý texturou. Textura je vytvořena ve formě mipmapy se základním rozlišením 64×64 texelů. Při vykreslování stěny zmenšeného tělesa se vyberou dvě nejbližší textury z mipmapy a z těchto se lineární interpolací vypočtou dvě barvy. Výsledná barva je vyčíslena pomocí další lineární interpolace těchto dvou barev.
Jedná se o demonstrační příklad, který připomíná význam a tvorbu mipmap. Vyčíslení barev texelů v mipmapách je provedeno programově, zatímco ve druhém demonstračním příkladu je pro změnu velikosti textur na jednotlivých úrovních mipmapy použita funkce gluScaleImage().
Zdrojový kód prvního demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.
Obrázek 1: Screenshot prvního demonstračního příkladu
Jak již bylo uvedeno v předchozím odstavci, je ve druhém demonstračním příkladu ukázáno, jakým způsobem je možné použít funkci gluScaleImage() pro vytvoření mipmapy. Tato funkce se volá na vstupní texturu o velikosti 64×64 texelů s tím, že se postupně vytváří textury (tj. součásti mipmapy) o velikosti 32×32, 16×16, 8×8, 4×4, 2×2 a konečně 1×1 texelů.
Zdrojový kód druhého demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.
Obrázek 2: Screenshot druhého demonstračního příkladu
6. Obsah dalšího pokračování
V dalším pokračování tohoto seriálu si popíšeme zbývající funkce pro manipulaci s rastrovými obrázky, především funkce pro tvorbu dvourozměrných a trojrozměrných mipmap.
7. Seznam funkcí OpenGL a GLUT zmíněných v této části
glPixelStorei()glPixelStoref()
glDrawPixels()
glTexImage1D()
8. Nové funkce popsané v této části
gluScaleImage()gluBuild1DMipmaps()
9. Zkomprimovaná verze článku i s přílohami
Zkomprimovaná verze tohoto článku i s přílohami a demonstračními příklady je uložena zde.