Hlavní navigace

Grafická knihovna OpenGL (17): přidání "mlhy"

21. 10. 2003
Doba čtení: 7 minut

Sdílet

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žívána v různých aplikacích, protože je na první pohled efektní a současně umožňuje urychlit vykreslování celé scény.

Mlha

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 ve 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ázku použití této metody znázorňuje první 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.

Prostorová scéna s aplikovaným efektem mlhy
Obrázek 1: Prostorová scéna s aplikovaným efektem mlhy

Princip efektu

Na první pohled vypadá tento efekt velmi složitě. Ve skutečnosti je jeho princip velice 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 následně 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.

Princip efektu mlhy
Obrázek 2: Princip efektu mlhy

Funkce mlhy a parametry této funkce

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:

  1. vzdálenosti fragmentu od pozorovatele
  2. nastavené funkci hustoty mlhy (viz dále)
  3. parametrech funkce hustoty mlhy

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:

  1. Nejjednodušší funkcí je lineární funkce. Tuto funkci lze vyjádřit vztahem
    f=(end-z)/(end-start),
    kde start a end určují počáteční a koncovou vzdálenost, ve kterých hodnoty lineárně klesají. Mimo rozsah těchto parametrů se funkční hodnoty nepočítají. Výhodou je při použití této funkce vysoká rychlost zobrazování, ale efekt mlhy neodpovídá realitě.
  2. Poněkud složitější funkcí je exponenciální funkce se záporným exponentem, tj. funkce je klesající:
    f=e-density*z,
    kde density je hustota mlhy a z je vzdálenost fragmentu od pozorovatele. Tato funkce je na výpočet poněkud složitější než funkce předchozí, ale vizuální výsledky lépe odpovídají realitě.
  3. Poslední, nejsložitější funkcí, je
    f=e-(densityz)2 (pokud se dvojitý exponent zobrazí v prohlížeči špatně: f=e^-((densityz)^2))
    Člen density představuje opět hustotu mlhy, z je vzdálenost fragmentu. Výpočet této funkce je nejpomalejší, výsledky však nejlépe odpovídají realitě, kde se také intenzita světla snižuje se čtvercem vzdálenosti. Použití této funkce na počítači má však za následek velmi rychlé „mizení“ objektů, proto doporučuji použít spíše předchozí funkci.

Vliv typu funkce a parametru hustoty mlhy na průběh směšovací hodnoty je zobrazen na třetím obrázku.

Hustota mlhy v závislosti na vzdálenosti fragmentu od pozorovatele
Obrázek 3: Hustota mlhy v závislosti na vzdálenosti fragmentu od pozorovatele

Mlha a OpenGL

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říkazemglDisa­ble(GL_FOG). Kdykoliv za 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, &param).

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


Použití mlhy

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 tato 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 ve 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í ve všudypřítomné mlze, která hře dodává zajímavou atmosféru. Podobný princip je vidět i v 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. Na rozdí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í.

Demonstrační příklady

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.

UX DAy - tip 2

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.

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