Dnešní pokračování seriálu o nadstavbové grafické knihovně GLU bude věnováno popisu funkcí, které lze použít pro pokročilejší manipulaci s rastrovými obrázky, tj. s bitmapami či pixmapami, které se mají použít pro texturování. Mezi operace, které lze s rastrovými obrázky provádět, patří zejména změna jejich měřítka a tvorba takzvaných mipmap, které se uplatní primárně při texturování, jejich použití je však možné i při aplikaci dalších algoritmů počítačové grafiky.
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.
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 zabalování pixmapy se korektně používají nastavené režimy rozbalování a zabalování 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í:
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í funkce gluErrorString(). Většinou se vrací chybové kódy GLU_INVALID_ENUM, GLU_INVALID_VALUE nebo GLU_OUT_OF_MEMORY.
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 (http://www.root.cz/clanek/1974), zde si pouze rychle zopakujme přednosti mipmap při texturování:
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.
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():
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.
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 64x64 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 64x64 texelů s tím, že se postupně vytváří textury (tj. součásti mipmapy) o velikosti 32x32, 16x16, 8x8, 4x4, 2x2 a konečně 1x1 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
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.
Zkomprimovaná verze tohoto článku i s přílohami a demonstračními příklady je uložena zde.