Lekce 13 - 3D bludiště v XNA - Vertex a index buffer
Vítejte po dvacáté třetí. V předchozí lekci, 3D bludiště v XNA - Hráčská kamera, jsme si vytvořili kameru pro hráče.
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ě, 3D bludiště v XNA - Hardwarové instancování poprvé, 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žením následujícího souboru souhlasíš s licenčními podmínkamiStaženo 571x (99.7 kB)