Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
OpenGL -Jednoduché efekty 1
open gl
24. ledna 2002, 00.00 | Tak a máme tu další díl seriálu věnovanému OpenGL. Dnes se pokusíme z dosavadních znalostí něco malého vykouzlit. Vyzkoušíme si jednoduché efekty za pomocí blendingu,
jedné textury a hromady polygonů.
Dnes uvidíte, že i malé laciné efektíky mohou vypadat dobře, když se správně naaranžují. Pokusíme se využít jedinou texturu, pro vytvoření jednoduchého efektu. Tak například na obrázku, kde vidíte galaxii (aspoň mi tak připadá). Není to nic jiného než asi 50 polygonů stočených do šroubovice, každý polygon je pokryt texturou hvězdy a díky blendingu je každá hvězda jinak obarvená. Každá má nastavenou průhlednost.
Takže se vám pokusím popsat algoritmus, který vytvoří galaxii z hvězd.
Začneme tak, že pro popis každé hvězdy nám bude sloužit struktura stars.
|
V této struktuře uložíme informaci o barvě hvězdy, vzdálenost od středu zavinutí a úhel pootočení každé hvězdy. Teď už můžeme popsat každou hvězdu zvlášť. Myslím, že postačí asi 50 hvězd.
Další část programu je naprosto banální a stejná s předchozími díly. Nemusím vám připomínat načtení textury do paměti pod ukazatel texture[0].
Přeskočíme do funkce InitGL, zde nastartujeme výchozí stav, kdy poskládáme všech 50 hvězd za sebe do řádku.
|
Výchozí stav je potřeba k nastartování celého programu, to znamená, že zvolíme náhodně barvu hvězdy r,g,b. Úhel otočení ve výchozím stavu je 0. Další důležitá věc je dist (distance) , vzdálenost každé hvězdy od středu. Teď musíme zajistit aby hvězdy byly průsvitné a toho dosáhneme aktivací blendingu.
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
glEnable(GL_BLEND);
Teď přejdeme k funkci DrawScene. Nyní potřebujeme zajistit, aby jednotlivé hvězdy rotovali kolem středu a navíc se každá hvězda bude přibližovat ke středu. Při každém průchodu smyčkou poslední hvězda zmizí a na první pozici se objeví nová hvězda, co nejdále od středu. Tím jak algoritmus postupně pokračuje vzniká šroubovice.
|
Tato smyčka má na starost přepočítávat polohy všech hvězd. Cyklus prochází každou hvězdu zvlášť a přepočítává nové pozice. A jelikož se to špatně vysvětluje slovně pokuste se zorientovat v komentáři k výše uvedenému kódu, je myslím dostatečně okomentován.
Do programu jsem zabudoval možnost měnit náhled na scénu. Pomocí kláves page up a page down můžete přibližovat a vzdalovat scénu. Scéna se natáčí pomocí horní a dolní šipky. A když dobře natočíte scénu a vhodně ji přiblížíte, nevypadá to špatně.
Program je ke stažení ZDE (402 KB).
Oheň
V další části článku se budeme zabývat hořením ohně. Oheň je součástí našeho života a setkáme se s ním na každém kroku: u plynového sporáku, u táboráku, cigaretu si bez ohně také nezapálíte . A tím docházím, k jednomu otřesnému závěru, zkrátka oheň je nezkrotný živel a může napáchat spoustu škody, ale i spoustu dobra.
Já vás naučím, jak založit malý táboráček na obrazovce vašeho počítače, aniž by jste použili sirky a aniž by jste mohli vyhořet.
Již dlouhou dobu jsem se chystal napsat článek o elektronickém ohni, jak ho zapálit (a přitom se nepopálit), ale dlouho jsem váhal, protože na internetu je několik výborných článků, které algoritmus hoření ohně vysvětlují. Asi nejlepší algoritmus hoření ohně popisuje na svých stránkách Radovan Urban.
Přesto si myslím, že má smysl toto téma dále rozvádět, protože zmiňované články
se nepokoušeli tvořit oheň v OpenGL. Většina algoritmů tohoto druhu byla psána
v assembleru (kvůli rychlosti) a využívala pouze 256 barev.
Jelikož byl algoritmus již tolikrát popsán, připomenu ho jen stručně.
Máme definované dvourozměrné pole, které můžeme pojmenovat barva. Pro toto
pole zvolíme vhodnou velikost, například 30*50. Před zapálením ohně :) vynulujeme
celé pole barva.
Hoření ohně je neustále se opakující cyklus, ale aby vůbec něco hořelo budeme
potřebovat palivo (obdobně jako u skutečného ohně). To nechám na vás, jestli
zvolíte dřevo z lesa nebo brikety. Já bych doporučoval spíše 1 pixel. Takže
zpět k poli barva. Toto pole si představte jako sloupec plamene. Jedna buňka
v poli představuje jeden pixel ohně. A každý tento jeden bod v plameni má svou
intenzitu (0 - není oheň, 255 - hořííí). A aby oheň hořel, musíme do něj přikládat
palivo, tak do pole barva přiložíme na poslední řádek (libovolně zde umístíme
body o intenzitě 255). Nezaplníme však tento řádek úplně, protože potřebujeme
určitou nahodilost. V každém kroku hoření vygenerujeme nový řádek s palivem.
A teď si musíme něco povědět o samotném hoření ohně (paliva), které již máme
připravené. V každém kroku hoření ohně musíme projít celé pole barva od vrchu
dolů a přepočítáme každý pixel ohně. Přepočítáme jej podle tzv. průměrných barev.
Volíme průměr ze 4 bodů z pole barva.
přepočet každého pixelu (procházíme pixely od vrchu dolů, zleva doprava):
barva(x,y) = (barva(x-1, y+1)+ barva(x, y+1)+barva(x+1, y+1)+barva(x, y+2)/4)
Pokud se chcete podívat na můj pokus, dál jsem vám ho ke stažení ZDE (300 KB). Je dělaný v DelphiX.
Podobných příkladů na toto téma najdete na internetu desítky, avšak většina si vystačí s interpretací ohně přes pixely. Já jsem dostal nápad, jakým způsobem tento bezvadný algoritmus nepatrně vylepšit - předělat do OpenGL.
Oheň v OpenGL
Ještě si vzpomínáte na galaxii, o které jsem psal o něco výše (aby ne). Co takhle využít stejných hvězd k tomu, abychom rozhořeli malý plamínek, jaký vidíte na obrázku.
Místo pole barva, jsem si pole na generování ohně pojmenoval ohen, a ohen1. Protože v příkladu, který se vám snažím představit, jsou pro lepší výsledek použity 2 plameny. Ale zde v textu vám přiblížím pouze jeden, protože u druhého plamene je všechno stejné.
1) Generování paliva
|
Tento kód vygeneruje na předposledním řádku v poli ohen náhodně palivo. Podle toho, jakým způsobem generujeme tento řádek, zajistíme u ohně jeho proměnlivost (mihotání plamene).
2) Hoření ohně
|
Procházíme jednotlivé řádky našeho myšleného ohně v poli ohen a přepočítáváme hodnoty. Vypočítáváme průměr čtyř bodů a od výsledku odečteme 1 (to sice nemusíme, ale oheň je hezčí). Odečtení 1 snižuje plamen, proto odečítat větší hodnotu nedoporučuji.
3) Vykreslení
|
A tady je ten slíbený rozdíl oproti běžným ohňům vytvořených z pixelů. Náš oheň se bude skládat z obdélníků, které jsou přes sebe naskládány v řadě za sebou a také pod sebou. Každý obdelník je pokrytý texturou hvězda z minulého příkladu. A pro každý obdélník se definuje také barva podobně jako v předešlém příkladu s tím rozdílem, že si vystačíme s barevnými složkami r, g (nebo jenom r) a tím dosáhneme odstínu žluté barvy. Všechny obdélníky mají nastavenou průhlednost.
Pro mou kartu GeoForce2 nebyl program žádným oříškem s byl plynulý v rozlišení 640*480. Malého zpomalení jsem se dočkal až při 1024*768. Musel jsem proto do programu přidat řádek, který odstraní vykreslování skoro černých plamínků.
if (ohen[cy][cx] < 0.25)continue;
Program doznal poměrně citelného zrychlení, při 1024*768 už byl naprosto plynulý.
Ještě bych se závěrem zmínil o tom, že celý plamen je asi 200x předpočítaný ve funkci glInit a uložený do display listů. Jednotlivé snímky ohně jsou vyvolávány přes glCallList.
Poznámka:
Čím pošlete oheň dál do pozadí, tím bude rychlejší (přes proměnnou zoom).
Tento oheň si můžete stáhnout ZDE (230 KB).
Doufám, že se vám dnešní uvedení do problematiky efektů líbilo, protože už mám pro vás připravené mnohem lepší lahůdky.
Obsah seriálu (více o seriálu):
- OpenGL - 1.díl Nastavení a jednoduché kreslení
- OpenGL - 2 díl Rotace objektů
- OpenGL v C++ Builderu (3.díl)
- OpenGL v C++ Builderu (4.díl)
- OpenGL v C++ Builderu (5.díl)
- OpenGL v C++ Builderu (6.díl)
- OpenGL -Jednoduché efekty 1
- OpenGL - 8. díl - 3D Font, JPEG textury
- OpenGL 9. díl - Bitmap Font
- OpenGL -10.díl Náčítání modelů ze souborů
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007