13. diel - 3D bludisko v XNA - Vertex a index buffer
Vitajte po dvadsiaty tretí. Nedávno som pod jedným článkom objavil otázku čo to je vlastne vertex buffer. Táto otázka sa mi celkom hodí, aj keď uznávam že mala byť zodpovedaná už skôr. Vlastne hneď na začiatku nášho snaženia. Iste si pamätáte ako sme sa pokúšali vykresľovať útvary z čiar a trojuholníkov. Zoberme si napríklad tretí diel, stiahnite si hotový projekt a ten použijeme ako východiskový bod. Len pre zopakovanie ak sa nemýlim tak sme pridali textúru na naše vertexy. Žiadne kolízie nás neťažilo, jo to boli časy. Pozrieme sa teda na to čo program robí. Vytvoril pár polí s vertexy a indexy a tie potom posielal do grafickej karty a následne ich vykresľoval. Nutné povedať že je posielal do grafickej karty zakaždým pred vykreslením, teda že pole sa nenachádzajú v pamäti grafickej karty. Nie je to moc žiadny veľký problém, keď máme len 4 vrcholy, ale čo keď to bude nejaká zložitá štruktúra, treba terén o 100 000 vrcholoch? Potom už viditeľný problém nastáva ale práve od toho tu máme vertex buffer.
Vertex a index buffer
Ako som už naznačil v úvode nie je to nič iné ako pole, ktoré je uložené v pamäti grafickej karty, takže práca s ním bude rýchlejší. Zaplatíme za to ale daň, zakaždým keď budeme potrebovať buffer modifikovať budeme si ho musieť stiahnuť do normálneho poľa, vykonať úpravy a tie potom neskôr opäť do buffera nastaviť. Dosť bolo teórie, poďme si to vyskúšať. Pridáme si dve nové premenné:
VertexBuffer krizekBuffer; IndexBuffer krizekIdx;
A naopak premennú krizekVert
a krizekIdx
odstránime. Síce na nás vyskáče veľa chýb, ale Neľakajte sa. Zatiaľ.
Pridáme typ premennej na tento riadok:
VertexPositionColor[] krizekVert = new VertexPositionColor[5];
A hneď nám hromada chýb zmiznú. Rovnako to vykonáme aj s poľom pre
indexy, iba ja som ho nazval idx
, ale ako je známe, mená nehrajú
rolu:
int[] idx = new int[] {
Ďalej do metódy LoadContent
vytvoríme inštanciu vertex
bufferu:
krizekBuffer = new VertexBuffer(GraphicsDevice, VertexPositionColor.VertexDeclaration, krizekVert.Length, BufferUsage.WriteOnly);
Pri tomto konstruktoru sa pozastavíme. Nie je totiž intuitívne. Prvý parameter je jasný, s touto premennou sme sa zoznámili už dosť detailne, avšak druhý parameter je nám zatiaľ neznámy. Vertex declaration, alebo ak slovensky deklarácie vertexu, hovorí grafickej karte, z čoho je presne zložený vertex. Presnejšie povedané koľko bajtov ktorá zložka zaberá a hlavne aký je jej význam. My máme len pozíciu a farbu, ale môžeme si nadefinovať vlastný typ vertexu ale to neprebiehajte. Tretí parameter je počet vertexov a na poslednom mieste je ako bude môcť byť s bufferom nakladané. Nám postačí aby bol len pre zápis. (Samozrejme len pre zápis zo strany procesora, pre grafickú kartu bude k dispozícii pre čítanie) Teraz môžeme nastaviť dáta a tým je odoslať do pamäte grafickej karty:
krizekBuffer.SetData<VertexPositionColor>(krizekVert);
O index buffera som zatiaľ ešte okrem nadpisu nepovedal vôbec nič. Ale
funguje to úplne rovnako. Iba neuchovávame vertexy ale indexy podľa ktorých
sa potom vertexy prepájajú. V metóde LoadContent
teda vytvoríme
inštanciu index bufferu:
krizekIdx = new IndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, idx.Length, BufferUsage.WriteOnly);
A opäť sa zastavíme pri konstruktoru. Prvý parameter je nás starý
známy, druhým určujeme veľkosť indexov. Pričom 32 bitov zodpovedá typu
int
a 16 bitov typu short
. Tretí parameter je počet
indexov a naposledy opäť ako bude môcť byť s bufferom nakladané. Dáta si
opäť do buffera nastavíme:
krizekIdx.SetData<int>(idx);
Prípravu máme hotovú a tak sa posunieme k vykresľovanie. Starý riadok zakomentujeme a tým sa snáď zbavíte aj všetkých chýb. Vykresľovanie s pomocou bufferov je na viac ako jeden riadok. Najprv musíme obaja buffer nastaviť ako aktívny:
GraphicsDevice.SetVertexBuffer(krizekBuffer); GraphicsDevice.Indices = krizekIdx;
A teraz s ich pomocou všetko vykreslíme. Použijeme metódu
DrawIndexedPrimitives
:
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.LineList, 0, 0, 5, 0, 4);
Na môj vkus trochu moc parametrov, rozoberieme si ich. Prvá je, akým spôsobom sa majú objekty vykresľovať. Prvá nula, k čomu toto presne je nedokážem povedať, ale keďže to je podľa popisu báza, tak 0 by nemala byť na škodu. Druhý parameter je pre mňa tiež neznámy, takže nula. Tretí parameter je, koľko vertexov chceme, aby bolo k vykresľovanie použité, takže 5. Posledné nula je offset v bufferu s indexmi, takže tiež nula a na záver koľko objektov budeme kresliť. Ak by niekto z vás mal nejaké ďalšie informácie ohľadom významov, ma neznámych parametrov, tak sa určite ozvite v komentároch.
Napodiv je to všetko. Ak teraz program spustíte tak by ste mali dostať rovnaký výsledok ako s predchádzajúcim kódom. Jediný rozdiel je však v uložení vertexov v pamäti. Dobré je tiež podotknúť, že nahrávame ak modely, tak ich dáta sú uložené práve pomocou bufferov a sú teda už k dispozícii u grafickej karty.
XNA ponúka aj triedy s dynamickými buffer, nijako sa nelíši od týchto jenoduchých, len majú v sebe optimalizácie, ktoré umožňujú jednoduchú modifikáciu.
A to by bolo myslím pre dnešok všetko. Nabudúce si skúsime zlepšiť rýchlosť vykresľovanie u bludisko. Ako zatiaľ neprezradím, ale je jasné že budeme buffer potrebovať a že nám ukážu svoju pravú silu. Čakám tiež na prípadné otázky v komentároch.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkamiStiahnuté 523x (99.7 kB)