Flame - dokumentace

Vytvořil Martin Petříček
Muj Email

Obsah

Stručný popis programu

Program zobrazí hořící dům a vedle něj hořící táborák, čímž demonstruje fungování shaderů na dvou ohních různého umístění, parametrů a velikosti.
Scéna je uložena v samostatném souboru a je libovolně editovatelná bez nutnosti rekompilace.
Pro korektní fungování 'heat haze' efektu je potřeba aby ovladače a grafická karta podporovaly rozšíření EXT_framebuffer_object (v Nvidia ovladačích podpora od verze 76.64 z 1.6.2005)
Pokud nemáte kartu nebo ovladače podporující toto rozšíření, můžete tento efekt vypnout (do konfiguračního souboru config.txt připište usefbo=0) za cenu snížení grafické kvality

Framebuffer objekty v programu

V programu je využito rozšíření EXT_framebuffer_object následujícím způsobem:
Na začátku se vytvoří 2 offscreen framebuffer objekty o rozměru stejném jako obrazovka.
První obsahuje colorbuffer a depthbuffer, druhý jen colorbuffer (depth buffer by byl u něj zbytečný)
Bohužel jsem nepřišel na způsob jak přiřadit finální framebuffer (t.j. obsah obrazovky) jako texturu, nenašel jsem žádnou funkci která by to umožňovala (tím bych mohl ušetřit jedno kopírování z framebufferu do obrazovky na konci renderování scény). Tudíž jako poslední krok při renderování je nutné vzít celý obsah prvního framebufferu a zkopírovat ho na obrazovku. Na druhou stranu pokud bychom chtěli v tomto kroku přidat nějaký další postprocessing efekt, mohl by být téměř zadarmo (data se musí stejně zkopírovat, pokud by byl efekt jednoduchý, tak by nemuselo dojít ke snížení framerate)
EXT_framebuffer_object je narozdíl od pbufferu multiplatformní (není omezen na Windows) a není nutné vytvářet více kontextů.
V programu využívají dvou framebufferů shadery fsHeat a fsHeatCopy.
fsHeat vezme obsah části prvního framebufferu, kam se vše renderuje a tuto část se zvlněním přenese do druhého framebufferu. fsHeatCopy pak tuto část překopíruje zpět.

Testy funkčnosti a rychlosti

Program byl testován a shledán funkčním na těchto konfiguracích:
Geforce 6800, Windows XP 32bit, Nvidia ovladače verze 77.76
Geforce 6800, Linux Gentoo 64bit, Nvidia ovladače verze 76.76
Geforce 6800, Linux Debian 32bit, Nvidia ovladače verze 76.67
Testována byla též Geforce 4200 - program na této kartě neběží (příliš složité shadery).

Test rychlosti na Geforce 6800 GT, Athlon64/3000+ s vypnutým FSAA a anizotropickým filtrováním.
RozlišeníRychlost (FPS)
1024x768229
1600x1200100
2400x180048
Je vidět, že závislost FPS na počtu pixelů v obraze je praktický lineární, tedy většinu výkonu GPU spotřebují fragment shadery.

V rozlišení 1600x1200 jsem zjišťoval, kolik které efekty spotřebují času
Celá scéna (1600x1200)10.00 ms
Vykreslení statické scény 0.45 ms
Plamen (vsSmoke,fsSmoke) 4.15 ms
Kouř (vsFlame,fsFlame) 1.75 ms
Glow efekt (vsBillboard,fsGlow) 0.75 ms
Heat haze efekt (vsBillboard,fsHeat,fsHeatCopy)2.00 ms
Zkopírováni framebufferu do obrazovky1.00 ms

Popis shaderů

Parametry vyskytující se ve více shaderech:
centerStřed objektu (v souboru scene.txt je to parametr "move")
eyePozice oka (kamery)
eyedirSměr kterým se oko (kamera) dívá
eyeupVektor "up" u kamery (směr nahoru)
ftex13D šumová textura č.1
ftex23D šumová textura č.2
modelViewProjModelViewProjection matice
timePočítadlo času (v milisekundách)

vsBillboard

Vertex shader zajišťující že daný objekt bude pořád natočen stejným směrem ke kameře (Ve spojení s modelem flat lze použít jako billboard sprite)

fsGlow

Shader generující texturu s danou barvou a průhledností uprostřed, přecházející k okrajům plynule k naprosté průhlednosti. Vzniklá "kruhová" textura se dá ve spojení s billboard sprite dobře použít pro efekt záře kolem nějakého objektu.

fsHeat

Fragment shader pro první průchod 'Heat haze' efektu (tetelení vzduchu). Jako texturu použije aktuální obsah framebufferu, výsledek (zvlněný výřez obrazovky) se ukládá do druhého framebufferu ze kterého se pak zpět překopíruje pomocí fsHeatCopy do prvního framebufferu. "Amplituda" u tetelení vzduchu klesá s rostoucí vzdáleností od pozorovatele, efekt je nezávislý na rozlišení obrazovky. Ke kopírování dochází nikoliv pro celý framebuffer ale jen pro jeho část na které je aplikován tento efekt, takže mnoho malých (míněno výsledná velikost na obrazovce) zdrojů telelení vzduchu nesníží nijak drasticky výslednou framerate.

fsHeatCopy

Fragment shader pro druhý průchod 'Heat haze' efektu. V podstatě pouze překopíruje úsek obrazovky z offscreen bufferu na obrazovku. Kopíruje se s transparencí, takže ve vlnění trochu prosvítá originální obrys.

vsFlame

Vertex shader pro samotný plamen. Předpokládá, že dostane objekt přibližně kruhového až čtvercového víceméně konvexního tvaru, představující deformovanou mřížku o přibližně 40-150 dělení po obvodu a 10-25 po výšce.
Tento shader mřížku deformuje v závislosti na čase, aby vznikl dojem plápolajícího plamene.
Pro nejlepší efekt je dobré mít 3-5 zmenšujících se stejných objektů vnořených do sebe. Parametry:
flamewidth Šířka plamene
flameheightVýška plamene
randomness Jak moc se tetelí plameny. "Standardní" hosnota je 1, čím větší, tím více se plameny telelí

fsFlame

Fragment shader pro samotný plamen. V něm se počítá textura plamene za pomocí dvou trojrozměrných 3D šumových textur.

vsSmoke

Vertex shader pro kouř vycházející z plamene. Předpokládá na vstupu kužel, válec nebo podobný objekt, pozici vertexů nemodifikuje, pouze nastavuju data pro fsSmoke
Oproti kouři generovanému např. pomocí billboard sprites je "více trojrozměrný".
Parametry:
centerPozice středu základny kouře

fsSmoke

Fragment shader pro kouř vycházející z plamene. Kouř je generován pomocí dvou trojrozměrných 3D šumových textur.
Lze nastavit barvu kouře (brána barva z glColor)
Parametry:
smokewidthŠířka kouře (jak je sloupec kouře široký) - ovlivňuje texturu
smokespeedRychlost stoupání kouře

float rnd(float3 i);

Pro daný třírozměrný vektor vrátí pseudonáhodné číslo z intervalu [0,1].

float shift(float i,float lo);

Převede čísla z intervalu [0,1] na interval [1-lo,1+lo]

float sin_shift(float3 rnd1,float3 rnd2,float time,float factor);

Sinusová funkce zadaná dvěmi náhodnými čísly, časem a amplitudou.

Popis programu

Konfigurace
Konfigurace programu je uložena v okomentovaném souboru config.txt
Záznamy v souboru jsou typu key=value
Pokud něco není v souboru uvedeno, vezme se default
font jméno souboru použitého jako textura pro font
font_x šířka fontu v pixelech/td>
font_y výška fontu v pixelech
fov field of view (úhel pohledu) ve stupních
fullscreen 0 - program běží v okně, 1 - program běží fullscreen
width šířka okna v pixelech
height výška okna v pixelech
kbsensitivity citlivost klávesnice (rychlost pohybu)
scene jméno souboru se scénou
sensitivity citlivost myší
usefbo pokud je 1 (default), zapíná použití rozšíření EXT_framebuffer_object, čímž umožní některé efekty.
Scéna
Scéna je uložena v souboru scene.txt.
Je to obyčejný textový soubor s příkazy (# na začátku řádku značí komentář). Parametry příkazů jsou odděleny vždy mezerami.
PříkazParametryPopis
addobj Přidá aktuální objekt do scény
addshader Přidá aktuální shader do aktuálního objektu
camdistance vzdálenostNastaví počáteční vzdálenost kamery pro celou scénu
commonparam typ,jméno,hodnotaSpolečný parametr pro všechny shadery. Nastaví parametru jméno hodnotu hodnota u všech shaderů které takto pojmenovaný parametr obsahují. Shader však může tuto defaultní hodnotu předefinovat. Parametr typ určuje typ shaderu pro který se tento parametr bude aplikovat (v=vertex shader, f=fragment shader, *= oba typy)
color barvanastaví barvu pro aktuální objekt. Akceptována je třísložková nebo čtyřsložková barva (s průhledností) s hodnotami složek od 0 do 255
cone počet X segmentů, počet Y segmentů,šířka nahoře, šířka dole, výškaVytvoří objekt (kužel) a nastaví ho jako aktuální
cull cullingNastaví parameter cull pro aktuální objekt (backface culling - 0 vypíná, 1 zapíná).
cylinder počet X segmentů,počet Y segmentů,šířka,výškaVytvoří objekt (válec bez konců) a nastaví ho jako aktuální
cylindercaps počet X segmentů,šířka,výškaVytvoří objekt (konce válce) a nastaví ho jako aktuální
depthtest hodnotaZapnutí (1) nebo vypnutí (0) depth testu. Defaultně je zapnutý
distance x,y,zNastaví posun objektu který se bere v úvahu pro výpočet vzdálenosti. Může být jiný než skutečný posun (move), pokud není u objektu specifikován, bere se že jsou vzdálenost je rovna hodnotě move. Místo číselného parametru lze specifikovat last pro poslední použitou hodnotu vzdálenosti
empty Vytvoří objekt (prázdný objekt) a nastaví ho jako aktuální
fbo číslo FBO, smazání Vytvoří nový objekt typu "Přepínač framebuffer objektů". První parametr určuje číslo FBO (0 a 1, přičemž -1 je obrazovka). Pokud druhý parametr je 1, dojde při přepnutí ke smazání color a depth buffer v daném framebuffer objektu. Při přepnutí na obrazovku je do ní překopírován obsah framebufferu 0
farclip vzdálenostNastaví far clipping plane (ořezávání)
flat x1,y1,x2,y2,zVytvoří objekt (čtverec z x1,y1,z do x2,y2,z) a nastaví ho jako aktuální
house Vytvoří objekt (dům) a nastaví ho jako aktuální
move x,y,zNastaví posunutí aktálního objektu. Místo číselného parametru lze specifikovat last pro poslední použitou hodnotu posunu
nearclip vzdálenostNastaví near clipping plane (ořezávání)
needfbo Pokud je uvedeno u objektu, objekt není přidán do scény při vyplé podpoře EXT_framebuffer_object
param jméno,hodnotaNastaví aktuálnímu shaderu parametr. Ten může být buď statická hodnota (1 až 4 floaty) nebo dynamická hodnota (např 'parameter eyePosition $eye' nastaví parametr 'eyePosition' na proměnnou 'eye')
pseudocylinder počet X segmentů,počet Y segmentů,šířka,výška,exponentVytvoří objekt (hranatý skoroválec) a nastaví ho jako aktuální
rotate Nastaví rotaci aktuálního objektu
sameshader typ shaderuVytvoří stejný vertex (v) či fragment shader (f) - dle parametru - jako naposled použitý (i se stejnými parametry) a rovnou ho přidá do objektu
shader typ, soubor, jménoVytvoří nový shader a nastaví ho jako aktuální
texture jméno souboruNastaví texturu pro aktuální objekt (textury se nahrávají z adresáře data/)
transparent hodnotaNastaví transparenci u aktuálního objektu. Transparentní objekty jsou vykresleny po netransparentních a jsou před vykreslením seřazeny dle vzdálenosti. Nejprve jsou vykresleny objekty s transparencí nastavenou na 0 (dfaultní hodnota), potom s hodnotou 1 (transparentní objekty) a pak s hodnotou 2 (různé speciální efekty, atd...). Řazení objektů před kreslením se provádí stabilním algoritmem.
zwrite hodnotaNastaví parameter zwrite pro aktuální objekt (zápis do zbufferu) 1=zapnuto (default), 0=vypnuto
Dynamické hodnoty pro parametry shaderů.
Tyto hodnoty se každý frame updatují.
eye Pozice kamery (float3)
eye_d Úhel pohledu kamery (float3)
eye_u Úhel 'up' pohledu kamery (float3)
framebuffer Textura s framebufferem. Vždy obsahuje ten framebuffer z dvojice offscreen bufferů, který není aktivní.
modelview Modelview matice
modelview_projection ModelviewProjection matice
projection Projection matice
texture Texture matice
tex3d_1 První noise textura (3D textura)
tex3d_2 Druhá noise textura (3D textura)
time Tick counter v milisekundách (float)

Popis zdrojových kódů

Dokumentace je generována automaticky z okomentovaných zdrojových kódů pomocí programu doxygen
Dokumentace je generována do samostatného adresáře doc/html

Poznámky ke kompilaci

Pro Unix i Windows je třeba mít nainstalované kromě OpenGL knihoven a headerů také knihovny a headery pro CG a GLUT Unix
Pro kompilaci se používá g++ (GNU c++ compiler)
Pro kompilaci spusťte ./make, pokud bude házet chyby, tak ./make-gentoo64
Pokud je nainstalován doxygen, dojde i k vygenerování/přegenerování dokumentace.
Windows
Pro kompilaci se používá g++ (GNU c++ compiler) - je nutné mít nainstalovaný některý z portů g++, např. minGW
Pro kompilaci spusťte make.bat (bude v něm možná nutné přenastavit cesty)
Pokud je nainstalován doxygen (a je v PATH), dojde i k vygenerování/přegenerování dokumentace.