Hlavní navigace

OpenGL a nadstavbová knihovna GLU (18)

30. 11. 2004
Doba čtení: 7 minut

Sdílet

Tímto dílem seriálu o nadstavbové grafické knihovně GLU dokončíme část, ve které se zabýváme podporou práce s rastrovými obrázky, tj. bitmapami a pixmapami. Popíšeme si funkce pro vytváření dvojrozměrných a třírozměrných mipmap a na demonstračních příkladech si ukážeme použití automaticky generovaných dvojrozměrných mipmap při texturování.

Obsah

1. Vytvoření dvojrozměrné mipmapy
2. Příklad specifikace dvojrozměrné mipmapy
3. Trojrozměrné textury a jejich význam
4. Vytvoření trojrozměrné mipmapy
5. Demonstrační příklad
6. Obsah dalšího pokračování
7. Seznam funkcí OpenGL, GLU a GLUT zmíněných v této části
8. Zkomprimovaná verze článku i s přílohami
 

1. Vytvoření dvojrozměrné mipmapy

Funkce pro vytvoření dvojrozměrné mipmapy je prakticky totožná s funkcí pro vytvoření mipmapy jednorozměrné. Odlišnost spočívá především ve větším počtu parametrů, neboť je zapotřebí specifikovat i výšku vstupního rastrového obrázku. Hlavička této funkce má tvar:

GLint gluBuild2DMipmaps(
    GLenum       target,
    GLint        components,
    GLint        width,
    GLint        height,
    GLenum       format,
    GLenum       type,
    void        *data
);

Význam jednotlivých parametrů funkce gluBuild2DMip­maps() je následující:

  1. V prvním parametru target musí být jako typ zpracovávané cílové textury vždy předána hodnota GL_TEXTURE_2D. Pokud by v tomto parametru byla zadána hodnota jiná, vytvoření mipmapy by skončilo s neúspěchem a vrátil by se chybový kód GLU_INVALID_ENUM.
  2. Druhý parametr components, pomocí kterého je možné specifikovat počet barvových komponent v textuře, má stejný význam jako u minule popsané funkce gluBuild1DMip­maps(), tj. akceptuje následující hodnoty:
    1 (jedna barvová složka, průhlednost či luminance)
    2 (většinou luminance a průhlednost texelů)
    3 (tři barvové složky v barvovém formátu RGB)
    4 (tři barvové složky v barvovém formátu RGB s průhledností alfa)
  3. V parametru width je předána šířka vstupního rastrového obrázku, která je specifikovaná v pixelech. Údaj o šířce by měl být roven celočíselné mocnině dvou, jinak se před vlastní konstrukcí mipmapy rastrový obrázek pomocí funkce gluScaleImage() automaticky zvětší či zmenší na nejbližší hodnotu, jež je mocninou dvou. Díky této změně rozlišení obrázku může dojít k jeho deformaci.
  4. V následujícím parametru height je předána výška vstupního rastrového obrázku, taktéž uvedená v pixelech. O hodnotě výšky obrázku platí stejné informace jako o jeho šířce. Pro další zpracování mipmapy je nejvhodnější, aby původní šířka i výška rastrového obrázku byla mocninou dvou a aby tyto hodnoty byly stejné – pouze v tomto případě není provedena prvotní změna rozlišení obrázku, která nutně vede k jeho částečné vizuální degradaci.
  5. Hodnotou pátého parametru format se specifikuje formát barvy pixelů, tj. podrobnější informace udávající, z jakých barvových složek může být barva pixelu vytvořena. Povolené hodnoty tohoto parametru 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í alfa),
    GL_BGR_EXT (obrácený formát RGB),
    GL_BGRA_EXT (obrácený formát RGBA),
    GL_LUMINANCE (světlost texelů) a
    GL_LUMINANCE_AL­PHA (světlost spolu s průhledností al­fa).
  6. Parametr type má stejný význam jako u funkce gluBuild1DMip­maps() – specifikuje se v něm datový typ jednotlivých barvových složek pixelů s následujícím významem:
    GL_BYTE (8bitový integer),
    GL_BITMAP (bity spojené do vícebitových 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).
  7. V posledním parametru data je předán ukazatel na vstupní rastrový obrázek, tj. na pole hodnot jednotlivých pixelů, kde formát každého pixelu odpovídá hodnotám parametrů type a components.

Po vytvoření mipmapy je pro každou její úroveň zavolána funkce glTexImage2D(), takže uživatel již toto volání nemusí v aplikaci explicitně provádět. Pokud vytvoření jednotlivých textur v mipmapě proběhne bez chyby, vrátí se nula, v opačném případě se vrátí chybový kód, většinou GLU_INVALID_ENUM, GLU_INVALID_VALUE či GLU_OUT_OF_ME­MORY. Tento chybový kód lze opět převést na řetězec pomocí funkce gluErrorString()

2. Příklad specifikace dvojrozměrné mipmapy

Na základě výše zmíněné informace o automatickém generování mipmapy pomocí funkce gluBuild2DMip­maps() je možné vytvořit proceduru, která zajistí korektní nastavení všech parametrů mipmapy a následně provede uložení mipmapy do texturovací paměti grafického akcelerátoru:

//---------------------------------------------
// Nastavení parametrů textury a vytvoření
// mipmapy pomocí funkce gluBuild2DMipmaps().
// Tato funkce využívá globální proměnné
// textureName a texture.
//---------------------------------------------
void setTextures(void)
{
    // způsob uložení bytů v textuře
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // vygenerování jména jedné textury
    glGenTextures(1, &textureName);
    glBindTexture(GL_TEXTURE_2D, textureName);

    // opakování textury v obou směrech
    glTexParameteri(GL_TEXTURE_2D,
                    GL_TEXTURE_WRAP_S,
                    GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D,
                    GL_TEXTURE_WRAP_T,
                    GL_REPEAT);

    // volba filtrů při zvětšování a zmenšování
    glTexParameteri(GL_TEXTURE_2D,
                    GL_TEXTURE_MAG_FILTER,
                    GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,
                    GL_TEXTURE_MIN_FILTER,
                    GL_LINEAR_MIPMAP_LINEAR);

    // vytvoření mipmapy, tj. jednotlivých
    // textur, ze kterých se mipmapa skládá
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3,
                      TEXTURE_WIDTH,
                      TEXTURE_HEIGHT,
                      GL_RGB, GL_BYTE,
                      (void*)texture);

    // vylepšení zobrazování textur
    glHint(GL_PERSPECTIVE_CORRECTION_HINT,
           GL_NICEST);

    // způsob vykreslení textury
    glTexEnvf(GL_TEXTURE_ENV,
              GL_TEXTURE_ENV_MODE,
              GL_REPLACE);

    // povolení texturování
    glEnable(GL_TEXTURE_2D);
}

3. Trojrozměrné textury a jejich význam

V některých oblastech počítačové grafiky je nutné pracovat s rozsáhlými objemovými daty, pro jejichž rychlé vykreslení je možné využít specializovaných grafických akcelerátorů. Různých typů těchto akcelerátorů je však podstatně méně, než je tomu u akcelerátorů určených pro zobrazení modelů trojrozměrných těles složených z plošných polygonů. Hlavní důvody tohoto stavu jsou dva:

  1. Prvním důvodem je skutečnost, že objemová data jsou využívána v poměrně specifických oblastech, jako je medicína a materiálové inženýrství. Z hlediska výrobců grafických akcelerátorů se tedy nejedná o masový trh, čemuž odpovídá i počet vyrobených kusů, a tím pádem i výsledná cena těchto grafických akcelerátorů.
  2. Druhým důvodem jsou mnohem větší nároky na kapacitu a rychlost pamětí, které jsou v grafickém akcelerátoru pro zobrazování objemových dat použity. Zatímco nároky na paměť u akcelerátorů polygonové grafiky jsou mířeny do oblasti dostatečně velkého framebufferu a texturovací paměti (čtení či zápis z texturovací paměti sice není přísně lineární, ale je alespoň lokální, protože se vždy vykresluje pouze jedna či dvě na sebe nanesené textury), u grafických akcelerátorů pro objemovou grafiku je zapotřebí počítat s uložením celého objemu dat, přičemž v reálných aplikacích jsou běžná rozlišení 2563 voxelů a výše.

V budoucnu lze očekávat významné zvýšení požadavků na technické parametry nových grafických akcelerátorů pro zobrazení objemových dat, protože počet aplikací pro práci s těmito daty se sice pomalu, zato neustále zvyšuje. Také se stále častěji začínají používat zařízení, pomocí kterých lze objemová data získat.

Souběžně s tímto vývojem specializovaných grafických akcelerátorů se zavádí podpora pro trojrozměrné textury i do „běžných“ grafických akcelerátorů určených pro zobrazování polygonových modelů těles. Z toho důvodu jsou i v grafické knihovně OpenGL vytvořeny funkce pro specifikaci trojrozměrných textur.

4. Vytvoření trojrozměrné mipmapy

Jak již bylo řečeno v předcházející kapitole, podporují některé grafické akcelerátory a jim příslušející implementace OpenGL i práci s trojrozměrnými texturami. V těchto texturách nejsou jednotlivé texely představovány plošnými rastrovými elementy – pixely -, ale elementy objemovými, které se nazývají voxely (toto označení s písmenem x je vlastně parafrází na pixel, což je také slovní hříčka).

O vytvoření trojrozměrné mipmapy se postará funkce gluBuild3DMip­maps(), jež má následující hlavičku:

GLint gluBuild3DMipmaps(
    GLenum       target,
    GLint        components,
    GLsizei      width,
    GLsizei      height,
    GLsizei      depth,
    GLenum       format,
    GLenum       type,
    const void  *data
);

Pokud provedeme porovnání hlavičky funkcí gluBuild2DMip­maps() a gluBuild3DMip­maps(), zjistíme, že se liší pouze v parametru depth, který je použit jen u funkce gluBuild3DMip­maps(). V tomto parametru je předána hloubka trojrozměrné textury, která je zadána, podobně jako u předchozích dvou parametrů width a height, přímo v objemových elementech – voxelech.

Vytvoření mipmapy trojrozměrné textury se děje stejným způsobem jako u textury dvojrozměrné. Jediný rozdíl spočívá v tom, že jsou vytvořeny jednotlivé vrstvy textury, které představují její třetí rozměr a při zmenšování rozlišení textur v mipmapě se provádí slučování těchto vrstev.

5. Demonstrační příklad

Po překladu a spuštění (dnes jediného) demonstračního příkladu se zobrazí model tělesa, který je pokrytý plošnou 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 (tj. textura je na obrazovce menší než zmíněných 64×64 texelů) se vyberou dvě nejbližší textury z mipmapy a z těchto textur se lineární interpolací vypočtou dvě barvy. Výsledná barva je vyčíslena pomocí další lineární interpolace těchto dvou barev. Vytvoření mipmapy je přitom zajištěno funkcí gluBuild2DMip­maps().

Zdrojový kód prvního demonstračního příkladu je dostupný zde, jeho HTML verze se zvýrazněním syntaxe zde.

Screenshot prvního demonstračního příkladu
Obrázek 1: Screenshot prvního demonstračního příkladu

6. Obsah dalšího pokračování

Další část seriálu o nadstavbové grafické knihovně OpenGL GLU bude věnována takzvané teselaci polygonů, tj. programovému rozkládání polygonů na jednotlivé nepřekrývající se trojúhelníky. Teselaci je možné s výhodou využít zejména v případě, že jsou v nějakém modelovacím programu vytvářeny a exportovány stěny těles z plošek, jež nejsou konvexní – již v seriálu o OpenGL jsem se totiž zmínil o tom, že grafické akcelerátory mohou vykreslovat pouze konvexní polygony.

CS24_early

Pro korektní vykreslení je tedy nutné všechny nekonvexní polygony převést na trojúhelníky, které jsou samozřejmě již ze své geometrické podstaty vždy plošné a konvexní. Převod obecných nekonvexních polygonů na trojúhelníky je však pracný a náchylný k chybám, proto jsou v knihovně GLU zabudovány funkce, které tento převod za aplikačního programátora provedou automaticky.

7. Seznam funkcí OpenGL, GLU a GLUT zmíněných v této části

gluBuild1DMipmaps()
gluBuild2DMipmaps()
gluBuild3DMipmaps()
gluScaleImage()
 

8. 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.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.