13. díl - 3D bludiště v XNA - Vertex a index buffer

C# .NET XNA game studio 3D bludiště 3D bludiště v XNA - Vertex a index buffer

Vítejte po dvacáté třetí. Nedávno jsem pod jedním článkem objevil dotaz co to je vlastně vertex buffer. Tato otázka se mi docela hodí, i když uznávám že měla být zodpovězena již dříve. Vlastně hned na začátku našeho snažení. Jistě si pamatujete jak jsme se pokoušeli vykreslovat útvary z čar a trojúhelníků. Vezměme si třeba třetí díl, stáhněte si hotový projekt a ten použijeme jako výchozí bod. Jen pro zopakování pokud se nepletu tak jsme přidali texturu na naše vertexy. Žádné kolize nás netížily, jo to byly časy. Podíváme se tedy na to co program dělá. Vytvořil pár polí s vertexy a indexy a ty pak posílal do grafické karty a následně je vykresloval. Nutno říci že je posílal do grafické karty pokaždé před vykreslením, tedy že pole se nenacházejí v paměti grafické karty. Není to moc žádný velký problém, když máme jen 4 vrcholy, ale co když to bude nějaká složitá struktura, třeba terén o 100 000 vrcholech? Pak již viditelný problém nastává ale právě od toho tu máme vertex buffer.

Vertex a index buffer

Jak jsem již naznačil v úvodu není to nic jiného než pole, které je uloženo v paměti grafické karty, takže práce s ním bude rychlejší. Zaplatíme za to ale daň, pokaždé když budeme potřebovat buffer modifikovat budeme si jej muset stáhnout do normálního pole, provést úpravy a ty pak později opět do bufferu nastavit. Dost bylo teorie, pojďme si to vyzkoušet. Přidáme si dvě nové proměnné:

VertexBuffer krizekBuffer;
IndexBuffer krizekIdx;

A naopak proměnnou krizekVert a krizekIdx odstraníme. Sice na nás vyskáče hodně chyb, ale nelekejme se. Prozatím. Přidáme typ proměnné na tento řádek:

VertexPositionColor[] krizekVert = new VertexPositionColor[5];

A hned nám hromada chyb zmizí. Stejně to provedeme i s polem pro indexy, jenom já jsem ho nazval idx, ale jak je známo, jména nehrají roli:

int[] idx = new int[] {

Dále do metody LoadContent vytvoříme instanci vertex bufferu:

krizekBuffer = new VertexBuffer(GraphicsDevice, VertexPositionColor.VertexDeclaration, krizekVert.Length, BufferUsage.WriteOnly);

U tohoto konstruktoru se pozastavíme. Není totiž intuitivní. První parametr je jasný, s touto proměnnou jsme se seznámili již dost detailně, ovšem druhý parametr je nám zatím neznámý. Vertex declaration, nebo-li česky deklarace vertexu, říká grafické kartě, z čeho je přesně složený vertex. Přesněji řečeno kolik bajtů která složka zabírá a hlavně jaký je její význam. My máme jen pozici a barvu, ale můžeme si nadefinovat vlastní typ vertexu ale to nepřebíhejme. Třetí parametr je počet vertexů a na posledním místě je jak bude moci být s bufferem nakládáno. Nám postačí aby byl jen pro zápis. (Samozřejmě jen pro zápis ze strany procesoru, pro grafickou kartu bude k dispozici pro čtení) Nyní můžeme nastavit data a tím je odeslat do paměti grafické karty:

krizekBuffer.SetData<VertexPositionColor>(krizekVert);

O index bufferu jsem zatím ještě kromě nadpisu neřekl vůbec nic. Ale funguje to naprosto stejně. Pouze neuchováváme vertexy ale indexy podle kterých se pak vertexy propojují. V metodě LoadContent tedy vytvoříme instanci index bufferu:

krizekIdx = new IndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, idx.Length, BufferUsage.WriteOnly);

A opět se zastavíme u konstruktoru. První parametr je nás starý známý, druhým určujeme velikost indexů. Přičemž 32 bitů odpovídá typu int a 16 bitů typu short. Třetí parametr je počet indexů a naposled opět jak bude moci být s bufferem nakládáno. Data si opět do bufferu nastavíme:

krizekIdx.SetData<int>(idx);

Přípravu máme hotovou a tak se posuneme k vykreslování. Starý řádek zakomentujeme a tím se snad zbavíte i všech chyb. Vykreslování s pomocí bufferů je na více než jeden řádek. Prvně musíme oba buffery nastavit jako aktivní:

GraphicsDevice.SetVertexBuffer(krizekBuffer);
GraphicsDevice.Indices = krizekIdx;

A nyní s jejich pomocí vše vykreslíme. Použijeme metodu DrawIndexedPrimitives:

GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.LineList, 0, 0, 5, 0, 4);

Na můj vkus trochu moc parametrů, rozebereme si je. První je, jakým způsobem se mají objekty vykreslovat. První nula, k čemu toto přesně je nedovedu říci, ale jelikož to je podle popisu báze, tak 0 by neměla být na škodu. Druhý parametr je pro mě taky neznámý, takže nula. Třetí parametr je, kolik vertexů chceme, aby bylo k vykreslování použito, takže 5. Poslední nula je offset v bufferu s indexy, takže také nula a na závěr kolik objektů budeme kreslit. Pokud by někdo z vás měl nějaké další informace ohledně významů, mě neznámých parametrů, tak se určitě ozvěte v komentářích.

Kupodivu je to vše. Pokud nyní program spustíte tak byste měli dostat stejný výsledek jako s předchozím kódem. Jediný rozdíl je však v uložení vertexů v paměti. Dobré je také podotknout, že nahráváme-li modely, tak jejich data jsou uložena právě pomocí bufferů a jsou tedy již k dispozici u grafické karty.

XNA nabízí také třídy s dynamickými buffery, nikterak se neliší od těchto jenoduchých, pouze mají v sobě optimalizace, které umožňují snadnou modifikaci.

A to by bylo myslím pro dnešek všechno. Příště si zkusíme zlepšit rychlost vykreslování u bludiště. Jak zatím neprozradím, ale je jasné že budeme buffery potřebovat a že nám ukáží svou pravou sílu. Čekám také na případné otázky v komentářích.


 

Stáhnout

Staženo 176x (99.7 kB)

 

  Aktivity (1)

Článek pro vás napsal vodacek
Avatar
Vodáček dělá že umí C#, naplno se již pět let angažuje v projektu ŽvB. Nyní studuje na FEI Upa informatiku, ikdyž si připadá spíš na ekonomice. Není mu také cizí PHP a SQL. Naopak cizí mu je Java a Python.

Jak se ti líbí článek?
Celkem (3 hlasů) :
55555


 



 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!