V dnešní části seriálu o grafické knihovně OpenGL se budeme zabývat jednoduchou technikou pro přidání "mlhy" do vykreslované scény. Tato technika je často používaná v různých aplikacích, protože je na první pohled efektní a současně umožňuje urychlit vykreslování celé scény.
Grafická knihovna OpenGL podporuje metodu, pomocí které lze do vykreslované scény přidat takzvanou mlhu (fog). Jedná se o grafický efekt, při kterém se se vzrůstající vzdáleností od pozorovatele postupně mění barva vykreslovaných těles. V blízkosti pozorovatele (tj. malé vzdálenosti) má těleso svoji původní barvu (zadanou buď příkazem glColor*(), texturou nebo materiálem), ve velké vzdálenosti pak barvu mlhy. Pokud je barva mlhy totožná s barvou pozadí, dosáhne se vcelku realistického efektu, kdy se tělesa ztrácí v mlze nebo tmě. Barva mlhy a pozadí však může být odlišná, čehož lze využít pro tvorbu různých nerealistických efektů.
Ukázka jednoduchého použití této metody je zobrazena na prvním obrázku (obrázek je převzat z jiných zdrojů na Internetu). Z obrázku je patrné, že pouze travnatý povrch je zobrazen svou původní barvou (resp. barvou textury), vzdálenější povrch i budova se však ztrácí v mlze, která je, podobně jako pozadí, nastavena na šedou barvu.
Obrázek 1: Prostorová scéna s aplikovaným efektem mlhy
Na první pohled vypadá tento efekt velmi složitě. Ve skutečnosti je jeho princip velmi jednoduchý. Pomocí příkazů z grafické knihovny OpenGL se zadají základní vlastnosti mlhy, což ve skutečnosti představuje výběr jedné ze tří funkcí a nastavení parametrů těchto funkcí. Potom se při výpočtu barvy každého fragmentu získá jeho barva bez působení mlhy (tj. použije se například texturování nebo osvětlení) a potom se tato barva mísí s předem zadanou barvou mlhy. Poměr původní barvy fragmentu a barvy mlhy ve výsledné barvě je dán parametry funkce mlhy a vzdáleností fragmentu od pozorovatele (tato vzdálenost se stejně musí počítat, mininálně pro potřeby hloubkového bufferu). Princip tohoto efektu je naznačen na druhém obrázku.
Obrázek 2: Princip efektu mlhy
Jak již bylo popsáno v minulém odstavci, pracuje efekt mlhy tak, že se kombinuje původní barva fragmentu s barvou mlhy. To, jakým způsobem (resp. v jakém poměru) budou tyto barvy smíšeny závisí na třech faktorech:
OpenGL podporuje tři typy funkcí, které lze použít pro výpočet hustoty mlhy v místě fragmentu. Tyto funkce vlastně určují, jakým způsobem se bude měnit barva těles se vzdáleností od pozorovatele:
Vliv typu funkce a parametru hustoty mlhy na průběh směšovací hodnoty je zobrazen na třetím obrázku.
Obrázek 3: Hustota mlhy v závislosti na vzdálenosti fragmentu od pozorovatele
Efekt mlhy je zapotřebí před prvním použitím povolit nebo zakázat. Povolení se provede příkazem glEnable(GL_FOG), zakázání potom příkazem glDisable(GL_FOG). Kdykoliv v průběhu běhu aplikace se lze dotázat, zda je mlha zapnutá či nikoliv zavoláním funkce glIsEnabled(GL_FOG) nebo složitěji funkcí glGetBooleanv(GL_FOG, ¶m).
Dále je zapotřebí zvolit funkci, která určuje hustotu mlhy. Tato funkce se nastaví příkazem glFogi(GL_FOG_MODE, function), kde parametr function může nabývat hodnot: GL_LINEAR (první, lineární funkce), GL_EXP (druhá, exponenciální funkce) a GL_EXP2 (třetí, exponenciální funkce, jejíž hodnota závisí na kvadrátu vzdálenosti).
Dalším krokem je nastavení parametrů funkce a barvy mlhy. Parametry funkce se nastavují příkazy:
void glFogf( GLenum pname, GLfloat param ); void glFogi( GLenum pname, GLint param ); void glFogfv( GLenum pname, const GLfloat * params ); void glFogiv( GLenum pname, const GLint * params );
Tyto příkazy se liší typem a počtem parametrů, které lze předat. Parametr pname může nabývat hodnot GL_FOG_MODE (bylo probráno výše), GL_FOG_DENSITY (hustota mlhy pro exponenciální funkce), GL_FOG_START (bližší vzdálenost pro lineární funkci) a glFogEnd (větší vzdálenost pro lineární funkci). Pomocí příkazů glFogfv() a glFogiv() lze předat barvu mlhy. Parametr pname je nastaven na hodnotu GL_FOG_COLOR a parametr params je ukazatel na pole čtyř čísel vyjadřujících složky barvy, tj. RGB a průhlednost.
Následuje ukázka nastavení mlhy v aplikaci:
GLfloat fogColor[4]={0.5,0.5,0.5,1.0}; // barva mlhy glEnable(GL_FOG); // povolit mlhu fogMode = GL_EXP; // funkce pro mlhu glFogi(GL_FOG_MODE, fogMode); glFogfv(GL_FOG_COLOR, fogColor); glFogf(GL_FOG_DENSITY, 0.35); // hustota mlhy glHint(GL_FOG_HINT, GL_DONT_CARE); glFogf(GL_FOG_START, 1.0); // pouzito pro linearni funkci, tady zbytecne glFogf(GL_FOG_END, 5.0); glClearColor(0.5,0.5,0.5,1.0); // pouzijeme barvu mlhy pro vymazani sceny
Tento efekt lze použít v mnoha příkladech při zobrazování trojrozměrných scén. Pokud se podrobněji podíváme na princip, jakým se mlha počítá, zjistíme, že se nejedná o žádný extrémně náročný výpočet. Naopak, vzhledem k tomu, že se mlha počítá pro každý potenciálně viditelný fragment, je možné tento výpočet zabudovat přímo do grafického vykreslovacího řetězce a provádět s hardwarovou podporou. Proto je zejména na novějších grafických akcelerátorech (které provádí většinu výpočtů hardwarově případně s pomocí GPU) tento efekt velmi dobře použitelný.
Použitím tohoto efektu můžeme paradoxně zvýšit rychlost zobrazování některých scén. Můžeme totiž využít faktu, že vzdálená tělesa jsou díky mlze buď částečně nebo úplně neviditelná. Proto tyto tělesa nemusíme vykreslovat. Zejména ve scénách, kde se nachází velké množství složitých těles na velkém prostoru (typicky počítačové hry, kde jsou zobrazena auta, stromy apod.) může být díky odstranění těles z vykreslovacího procesu vykreslování až několikanásobně urychleno.
Princip "uschování" těles v mlze nebo tmě byl v minulosti častokrát použit v počítačových hrách a to i tehdy, když se vykreslování provádělo specializovanými algoritmy a ne pomocí OpenGL. Jmenujme například letecké simulátory (Chuck Yager`s Air Combat), nebo hry typu dungeon (Dungeon Master, série Ishar). Tyto hry byly vytvořeny pro relativně pomalé procesory typu 286 příp. 386 a proto se při vykreslování scény musely zvolit velmi rychlé algoritmy. Urychlení pomocí mlhy je vidět zejména v sérii Ishar, kde se jedná o klasický čtverečkový dungeon, ale hráč před sebou vidí jen několik políček, ostatní se ztrácí v šudypřítomné mlze, která hře dodává zajímavou atmosféru. Podobný princip je vidět i Dungeon Masteru, kde se však hrací prostředí ztrácí ve tmě.
Mlhu (resp. stmívání hran se vzrůstající vzdáleností těles) lze použít i při vykreslování technických výkresů, kdy se zobrazují pouze hrany těles. Potom se místo neměnné barvy hran může použít mlha, která i bez složitějších výpočtů osvětlení dodá zobrazované scéně zdání prostorovosti. Narozdíl od stínování, kdy se počítá barva ve vrcholech a barva plošek případně hran se interpoluje, se mlha počítá až pro každý fragment, což v některých případech může znamenat zpomalení vykreslování.
V prvním demonstračním příkladu (HTML verze tohoto příkladu) je ukázáno jednoduché použití mlhy při vykreslování těles. Pozadí je nastaveno na šedou barvu, stejně jako barva mlhy, což je nejobvyklejší způsob, který se také nejvíce blíží realitě. Pro výpočet mlhy je použita exponenciální funkce.
Ve druhém demonstračním příkladu (HTML verze tohoto příkladu) je ukázáno zapínání a vypínání mlhy v průběhu vykreslování (jeden objekt je vykreslený se zapnutou mlhou, druhý objekt s mlhou vypnutou). Pozadí je nastaveno na černou barvu a barva mlhy na modrou, takže se dosahuje zajímavých světelných efektů. Pro výpočet mlhy je použita lineární funkce.
Třetí demonstrační příklad (HTML verze tohoto příkladu) navazuje na příklady vytvořené v předchozích dílech. Je dodána podpora pro mlhu s tím, že se dají nastavovat parametry mlhy (funkce hustoty, barva pozadí a mlhy).
Pro majitele pomalejších linek je zde k dispozici celý článek i s přílohami.