HTML

Survive Developement

Itt olvashatod a Survive! nevű játék fejlesztésének állapotát, lépéseit. És mi is lesz a játék? Egy zombis-túlélős játék, ahol elsősorban a csapatmunkára építkezve kell megpróbálni életben maradni egy kihalt városban. A terep teljesen a tietek, nincsenek szabályok: éljetek túl, ahogy tudtok!


Küldj e-mailt nekünk:
gilgamesco@gmail.com

Sikolyok

Ettől tépjük a hajunkat:

Friss topikok

  • Sir Butcher: A gyors mozgású ütközés-érzékelés majd a lövésnél lesz topic :D A második esetben teljesen igaza... (2012.04.05. 16:38) Ütközésérzékelés
  • _fpeti_: Halad ez. (2012.04.04. 22:01) Gravitáció
  • Sir Butcher: Az sem rossz, az tény :D Szerencsére egyelőre annyi különbözőt kell csinálnom, hogy esélyem sincs ... (2012.02.20. 21:48) Scenery - Még több látvány
  • Sir Butcher: Na, ideírom: obj-nél megoldottam a csontokat. Melléktermékként összejöttek, extra számítás nélkül ... (2011.12.02. 11:48) Model Animálás - a probléma, és a (vélt) megoldás
  • Burwor: "A tesztvárosban sétálgatva belefutsz egy házba, aminek hiányzik egy fala. Mit csinálsz?" Zárva a... (2011.11.10. 15:00) Sziduri - a grafmotor bemutatkozik

VertexDeklarációk, avagy: Hogyan beszélgessünk a videokártyával?

2011.09.18. 09:27 :: Sir Butcher

Elsőnek is szeretnék tájékoztatni mindenkit, hogy én sem lopom a napot, és szépen haladok. Elméletileg, ha minden jól megy, ma készen lesz a grafmotor szíve, és, reményeim szerint, sikerül 10.000 falat akadás nélkül betölteni, és használni. Ez a mai cél.

UPDATE:
A nagy tervekből természetesen nem lett sok minden. Belefutottam jópár legyőzendő akadályba, így a quadtree elkészülése, és életre hozása csúszik holnapra (remélem legalábbis, mert csak írni kell.)

Tehát, akkor lássuk, hogyan is néz ki az, amikor az XNA álltal megadott alaposztályok nem jók nekünk az adatátadáshoz.

Szerencsére, a kezdők dolgát megsegítendő, Microsoftnál készítettek nekünk előre jópár alapértelmezett vertex-típust, ami a legtöbb esetben megfelelő is. Egészen pontosan ezeket:

VertexPositionColor
VertexPositionTexture
VertexPositionNormalTexture
VertexPositionColorTexture

Ezeknek már a neveik is önmagában sokat elárulnak: Az első pozíciót és színt ad ád, a második pozíciót és textúra koordinátát, a harmadik pozíciót, normálvektort és textúrakoordinátát (Egyik sem textúrát, ez igazából a legfontosabb tény, csupán azt, hogyan is kell ráfeszíteni a textúrát a vertexjeinkre!) és végül, szerintem a legfölöslegesebb: a pozíció, szín és textúra (hogy ez miért jó, azt nem tudom, bár gyanítom arra, hogyha nem akarok mindenhova textúrát feszíteni, akkor ott szín lesz.)

 

Na igen ám, ez mind nagyon szép, és nagyon jó. De mivan akkor, ha én például két textúrát akarok átadni? Vagy esetleg valami egyéb adatot biztosítani a megjelenítéshez?

Erre lehetne használni a shaderek .SetParameter értékét, csak azzal egy baj van: ezek nem vertexenként, hanem a teljes megjelenítésre érvényesek. (Tehát adok egy textúrát, vagy egy színt, akkor az összesre, ami tartalmazza az adatot, az lesz érvényes.)

Ami számunkra nem jó. Vagyis egyelőre még a teszt fázisban igen, de mivel később ki akarom terjeszteni a motor lehetőségeit, tehát pl bump-mappinget alkalmazni [mert különben Steve bántalmazni fog :P] ezért egyszerűbb, ha már kapásból elkezdem a saját vertexdecleration-nomat használni.

public struct BWallVertex
    {
        public Vector3 Position;
        public Vector2 TexCoords;

        public BWallVertex(Vector3 Pos, Vector2 TexC)
        {
            Position = Pos;
            TexCoords = TexC;
        }

        public static readonly int SizeInBytes = sizeof(float) * (3 + 2);

        public static readonly VertexElement[] VertexElements =
        {
        new VertexElement(0,0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
        new VertexElement(0,sizeof(float)*3, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
        };
    }

És most gyanítom felvetődött a kérdés, hogy ez miért is jó? (A hozzáértőknél esélyesebb, mert ha alaposan megnézzük, ez igazából pontosan egyenlő a VertexPositionTexture alap struct-tal, ígyhát sok értelme nem volt szenvedni tegnap vele majd másfél órát.)

Elsőnek, mit is látunk itt? Haladjunk lépésről lépésre.

Elsőnek is, meghívjuk a konstruktorunkat, ami kér egy Pozíciót, és egy TextúraKoordinátát. Ez eddig teljesen okés. A trükkösebb rész a VertexElement-nél kezdődik, ugyanis ez határozza meg a CPU számára, hogy milyen adatokat is küldönk le a videokártya számára, illetve azt is, hogy ezek az adatok egészen pontosan mit is jelentenek. Hiszen nem elég az, hogy küldünk egy rakat bájtot, azt is el kell árulni, hogy mi micsoda, különben honnan tudná a videokártyánk, hogy ez szín, az pozíció? Ezt, illetve a küldendő adat halálpontos defínicióját adjuk meg a deklarációnkban. Én most egyelőre csak a pozíciót, illetve a textúrakoordinátát küldem el, de ügye a későbbiekben még ehez jön egy újabb textúrakoordináta, illetve a normálvektorok (már most is hozzáírhatnám, de minél kevesebb kód, annál kevesebb bug lehetőség).

Akkor, boncolgassunk!

new VertexElement(0,0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),

Az első szám a VertexElement( után jelzi, hogy hanyadik adatfolyam is lesz ez. Az alap szám (amit a játékok 80%-ánál használnak) a 0, vagyis nem állítunk fel a küldés sorrendjétől különböző prioritást. Úgyis egymás után küldöm, akkor minek variálni? Egyszerűbb a kódot lejebb rakni, de a lehetőség megvan, hogyha dinamikusan akarnám variálni.

A második szám közel sem ilyen egyértelmű, vagy egyszerű, vagy éppen kihagyható: ez határozza meg azt az offsetet, hogy az egymás utáni adatokban hol az egyik vége, és a másik eleje. Mivel a boncasztalunkon fekvő sor az első adatfolyam, így neki a kezdete a 0. bájtnál van. Ez okés, és egyszerű is. Na, de hol kezdődik a második? Ezt viszonylag könnyű kiszámolni (már ha végül sikerül megérteni). A következő paraméter jelzi, hogy Vector3-at fogok küldeni, vagyis 3 float számot, vagyis (mivel a float mérete 4 byte) 12 byte-al eltolva fog kezdődni a stream. Na, de ezt honnan tudja a földi halandó? Vagy megnézi az MSDN-en, vagy használja a remek kis parancsot, mégpedig a "sizeof"-ot, ami visszatérési értéke az adott típus mérete.

A következő a VertexElementMethod, amit, bevallom, nem sikerült megfejteni, mire való, ha jól értelmeztem, akkor a megjelenítést befolyásolja: de bárhol néztem, mindenki mindenhol Default-ot használt, tehát valószinűleg nekem is jó lesz. Ha mégse, akkor addigra megfejtem, mire való :)

Majd utána következik a legfontosabb: a VertexElementUsage - ez határozza meg, hogy az elküldött adat mégis micsoda. Jelen esetben Position lesz, vagyis ez határozza meg, hogy a 3D-s terünkben (vagy, ha a CPU-t akarjuk izzasztani a videokártya helyett, mert szadisták vagyunk, akkor a View és World és Projection mátrixokkal elvégezhetjük a számításokat már a programban, akkor a koordináták már a 2D értéket fogják tartalmazni, ekkor a videokártya szabira is mehet, az ő össz dolga, hogy a kapott értékeket bepakolja a memóriájába, ahonnan majd kiküldi a monitor felé (ha éppen olyan kedve van :P ).

Az utolsó 0 pedig szintén az esetek legnagyobb részében érdektelen, csupán arra való, hogyha egy adatot több módon is fel akarunk használni (van amikor kell, de kétlem, hogy számomra ez az elkövetkezőekben érdekes volna).

Na, tehát így nézne ki egy eléggé alap, és egyszerű példán az, hogyan is tudunk adatot küldeni úgy, ahogy azt mi szeretnénk. Természetesen ezt lehet (és sajnos, kell is) tovább bonyolítani, de véleménem szerint ez bemutatónak bőségesen elég, így is jó hosszú post lett - de azért sikerült a csendemet megtörni :)

És még egy utóirat, miért is nem lehet a CPU-val mátrixműveleteket végezni? Egészen egyszerűen azért, mert egy mátrixművelet 16 szorzás és 12 összeadás. 64 szorzás, és 48 összeadás. Első gondolatra ez nem tűnik soknak, igaz? Na, nekem van ügyebár 3 mátrixom, vagyis kapásból 48 192 szorzás, és 36 144 összeadás. Hát, istenem, ez se sok, elvégre a CPU másodpercenként műveletek milliárdjait tudja elvégezni, nem? De, ez így van. Csak, a mai célom 10.000 vertex-el művelet végzés, ami egészen pontosan azt jelenti, hogy minden egyes vertexre, másodpercenként 60x, el kell végezni ezt a 84műveletet, vagyis csak ez másodpercenként 50 millió plussz művelet, és azt is számításba kell venni, hogy nem csak mi végzünk munkát a CPU-val, tehát a teljes kapacitás csak töredéke a mienk. Persze, elvégezhető, de akkor mástól kell erőforrást elvenni, ami nem feltétlenül jó ötlet. A videokártya pedig pontosan ilyen jellegű feladatokra van kitalálva, ilyen soros feladatvégzés (mint a szorzás, vagy összeadás, és ezt a CPU-nál sokkal-sokkal gyorsabban el tudja végezni (alapból majdnem 10x olyan gyorsan, hiszen a hétköznapi kártyáknál is van legalább 10 shader proci - a profibbaknál ennél jóval több). Így a videokártya számára ez könnyed kis művelet, míg a procinál az értékes időből és kapacitásból veszünk el.
 

2 komment

Címkék: mátrix fejlesztés cpu videokártya gpu shader vertexdecleration

A bejegyzés trackback címe:

https://survivedev.blog.hu/api/trackback/id/tr903235379

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

_fpeti_ 2011.09.19. 20:16:41

"miért is nem lehet a CPU-val mátrixműveleteket végezni"

Csak szólok, hogy a 3 mátrixot össze lehet szorozni, és az eredménnyel kell csak a vertex koordinátákat szorozni - vagyis csak 1 mátrixxal - ami 16 szorzás, és 12 összeadás.

Egyébként ha csont alapú animációt akartok valaha is csinálni, akkor muszáj lesz cpu-n mátrixokat szorozgatni, és akkor ki is fog derülni, hogy nem is olyan lassú az a cpu. ;)

Sir Butcher · http://survivedev.blog.hu/ 2011.09.19. 20:59:46

Na, ezt a mátrixos dolgot tényleg teljesen elszámoltam, és elírtam, de javítottam, örök hálám :)

Tudom, hogy a modelleken kénytelen leszek dolgozni mátrixokkal, de a vertex munkáját át lehet pakolni a GPU-ra. És csak a videokártyához hasonlítva lassú a CPU :)

De ezt írtam is. Vagy akartam. Mindenesetre, a következőben már benne van XD
süti beállítások módosítása