diff --git a/app/blog/2013/11/05/lava-a-warlockban.md b/app/blog/2013/11/05/lava-a-warlockban.md new file mode 100644 index 0000000000000000000000000000000000000000..213f7cb7184b691636cd6b2287f8e980774512c1 --- /dev/null +++ b/app/blog/2013/11/05/lava-a-warlockban.md @@ -0,0 +1,29 @@ +--- +slug: lava-a-warlockban +title: Láva effekt a Warlock játékban +authors: vico +tags: [Game-Dev, grafika, Warlock] +--- + +Röviden szeretném bemutatni a Game-Dev fejlesztés alatt álló, Warlock nevű, játékában implementált lávát. <!--truncate--> +A játékban varázslók harcolnak egymással egy lávával körülvett területen, ahol a láva terjed, ezzel szűkítve azt a területet, amelyben nem sérülnek a játékosok. A Warlock felülnézetes, 2D játék. Eredetileg XNA 4.0 keretrendszerre épült, a grafikai profil pedig “Reach” volt, ugyanis cél volt, hogy mindegyikünk számítógépén fusson. Ez azt jelenti, hogy legfeljebb shader model 2.0 volt használható, amely erősen korlátozott. A korlátozás a használható utasítások halmazát szűkíti, és nem enged adott mennyiségnél több utasítást használni egy shaderben (pontos értékekért az MSDN-es leírás itt található: [link](http://msdn.microsoft.com/en-us/library/windows/desktop/bb509655%28v=vs.85%29.aspx)). + +## A láva megjelenése + +Az eredeti koncepció szerint a láva procedurális lett, így semmilyen előre megrajzolt vagy eltárolt textúrát nem igényel, hanem matematikai képletek írják le, amelyekbe véletlen számok adják a bemenetet. A Perlin zaj ([wiki szócikk](http://en.wikipedia.org/wiki/Perlin_noise)) egy jó alapot ad a lávának, “csak” annyi a teendő animált láva rajzoláshoz vele, hogy egy három dimenziós Perlin zajnak mindig egy metszetét kell kiszínezve megjeleníteni, a metszet síkja pedig folyamatosan halad az idővel előre. Ezt azért lehet megtenni, mert a Perlin zaj úgynevezett gradiens zaj, amelyek egyik tulajdonsága a folytonosság. A kiszínezés matematikailag egyszerű: egy olyan függvényt kell találni, amely a zaj egy-egy értékéhez egy színt rendel. Az ilyeneket játékstúdiókban általában a kinézetért felelős művészek állítják be GUI-n, a mi esetünkben közösen addig állítgattuk a számokat, amíg el nem értük a kívánt kinézetet. Az implementációnál azonban felmerült némi bökkenő: a shader model 2.0 erős korlátai miatt egyetlen pixel shaderben nem lehet implementálni a kívánt algoritmust. + +A megoldás végül az lett, hogy induláskor a CPU-n számolunk négy darab csempézhető Perlin zaj textúrát, majd ezeket ismételve, részben átlátszóan egymásra téve rajzoljuk ki. A láva animálása is megoldott ezzel a módszerrel: az egyes “rétegeket” véletlenszerű mozgással eltoljuk egymáshoz képest az idő függvényében. Ezzel a grafikus processzornak nagyon kis terhet jelent megjeleníteni a lávát, viszont cserébe induláskor némiképp megnőtt a szükséges várakozás. Egy másik tulajdonsága ennek a módszernek, hogy sokat nézve a lávát fel lehet fedezni az önismétlődést. + +## A láva határai, lávadarabok + +Már a fejlesztés korai szakaszában eldöntöttük, hogy lehessen plusz lávapacákat varázsolni a pályára, amelyek, mint a pályát körülölelő lávánál, szép lekerekített alakúak, szemben egy egyszerűbb, szögletes alakzattal. Emellett cél volt, hogy lehetőleg egyszerűen implementálható és gyorsan számolható legyen. + +Az első gondolatunkat, miszerint valamilyen spline-t használunk a láva határának meghatározására, elvetettük, ugyanis egy tetszőleges spline által határolt terület kitöltése nem triviális feladat. Az egyik lehetőség, hogy felbontjuk a területet háromszögekre, és azokat rajzoljuk ki. A másik lehetőség, hogy konstans adatként a spline-t átadjuk a pixel shadernek, egy teljes képernyőt lefedő téglalapot rajzolunk, és a pixel shader majd minden egyes pixelre eldönti, hogy belül vagy kívül van-e. Bármelyiket is választjuk, mivel a láva alakja változik, minden képkocka más és más alakú lávát fog tartalmazni, ráadásul a láva alakját szinkronizálni kell a hálózaton keresztül a játékosok között, így kívánatos, hogy kevés adatforgalmat generáljon. + +A második megoldás nem praktikus, mivel bonyolult shaderkódot igényel, ráadásul a Reach profil miatt ez nem lehetséges. Az első megoldás sokkal jobb alternatíva, azonban rejlik benne egy buktató: a spline-nak az alakja minden szempontból “szabálytalan,” emiatt a háromszögekre bontását valamilyen nem triviális algoritmussal kell megoldani, mint például a fülvágó algoritmus. Ekkor felismertük, hogy nincs szükségünk általános spline-ok támogatására, elég ha egy kört eltorzítunk, mert az is elég hihetően néz ki. Így született meg az általunk használt módszer: felveszünk pontokat egy körön, majd véletlenszerűen eltoljuk őket sugárirányban. Ezután a kapott törött vonalat elsimítjuk egyszerű Catmull-Clark subdivision módszerrel. Ennek a háromszögelése triviális, ugyanis két szomszédos csúcs a simított vonalon és az eredeti kör középpontja mindig olyan háromszöget eredményez, amely teljesen az alakzaton belül van. Ezt körbe végigcsinálva ki is töltjük. A másik jó tulajdonsága (ami a spline-ságból megmaradt), hogy a subdivision lépést elég a klienseken végrehajtani, a szervernek csak a kontrollpontokat kell átadnia. Több pacának a kezelését úgy oldottuk meg, hogy több ilyen alakzatot készítünk, mindegyiknél jegyezzük, hogy a belseje vagy a külseje a láva, így lehet akár olyat is csinálni, hogy egy varázsló új lávát varázsol a pályára, vagy megszüntet egy darabot. + +A Warlockban használt GUI keretrendszer elég korlátozott volt, emiatt úgy döntöttünk, hogy lecseréljük WPF-re. Ezzel a lépéssel arra is rászánta magát a csapat, hogy az XNA-t is kidobja a játék alól és a SharpDX nevű könyvtárral hajtja meg a játék egyes részeit, mivel így lehetett megoldani a Direct3D és a WPF közötti interoperabilitást a legegyszerűbben. Az a szemléletváltás is megtörtént, hogy újabb grafikus processzorok lesznek a minimum követelmény, így a korábbi korlátozások is feloldódnak. Ezzel lehetségessé válik az eredeti koncepció megvalósítása, miszerint teljesen shaderben, procedurálisan készül a láva textúrája, így ugyan többletteher kerül a GPU-ra, de cserébe nem kell semmit előre eltárolni vagy kiszámolni. Itt látható egy WebGL-ben készült prototípusa az új implementációnak, amely a Perlin zaj egy újabb változatát használja, amelyet szimplex zajnak neveznek. + +## Az új láva prototípusa + +<iframe src="https://www.shadertoy.com/embed/MsX3WX?gui=true&t=10&paused=true" allowfullscreen="" width="640" height="360" frameborder="0"></iframe> diff --git a/app/blog/authors.yml b/app/blog/authors.yml index 1468991b7190d3129082f3c85906e8fd78d88520..02f0ed9845bc4afd4d60a9e63f8fff7a19a4fa48 100644 --- a/app/blog/authors.yml +++ b/app/blog/authors.yml @@ -40,4 +40,8 @@ zolij: title: "-" url: https://pek.sch.bme.hu/profiles/zolij image_url: /img/authors/zolij.png +vico: + name: Heisenberger Viktor + title: "-" + url: https://pek.sch.bme.hu/profiles/vico