V tejto lekcii by som vás chcel oboznámiť s jednou užitočnou pomôckou v D3D. Doteraz sme vytvárali jednoduchšie objekty spájaním vertexov cez TriangleList, TriangleStip a TriangleFan. Na vytvorenie kocky v prvom prípade sme potrebovali 36 vertexov, 24 v druhom a 24 v treťom. Čo tak zmenšiť tento počet na 8. Ako je to možné ? No predsa použitím indexov.

Indexy (indices)

Indexy sú čísla ukazujúce na vertexy vo vertex buffery. Hodnota, ktorú index nesie, je offset vertexu vo VB. Offset nie je však udávaný veľkosťou v bitoch, ako to býva zvykom, ale poradovým číslom vertexu vo VB. Indexy sú typu Integer (16 bit) alebo Long (32 bit). Ak sa nechystáte indexovať viac ako 32768 vertexov, nemá zmysel Long používať.


Jedným dôvodom prečo indexy vznikli je fakt, že mnohokrát zbytočne plytváme prostriedkami. Ak sa zamyslíte nad tým, ako sme doposiaľ vytvárali kocku, tak zistíte, že 3 vertexy zdieľajú to isté miesto v priestore. Napr. na mieste č.5 sa nachádzajú vertexy z prednej, bočnej a hornej steny. A to nie je dobre. S pomocou indexov sa situácia mení. Našu kocku potom môžme vytvoriť pomocou 8 vertexov (červené bodky) a 36 indexov (presne ako pri Triangle List). Každý z indexov sa odkazuje na niektorý z 8 vertexov. Potom stačí rendereru predať zoznam indexov a kocka je na obrazovke.

Napriek tomu, že sa indexy javia ako bezchybné je ich použitie obmedzené.

Výhody:

  • menší počet vertexov. I keď na druhej strane vám pribudne nové pole indexov, ktoré je ale omnoho menšie ako vertexy. Index zaberie 2 (alebo 4) bajty, kdežto vertex aj 20.
  • rýchlejšie transformácie. D3D ľahšie vypočíta pozíciu pre 8 vertexov ako pre 24 napr. pri rotácii.
  • ľahšie sa animuje (meníte pozíciu iba u 8 vertexov)

Nevýhody:

  • jeden vertex zdieľajú 3 trojuholníky. Tým zdieľajú všetky jeho vlastnosti (pozíciu, farbu, normálový vektor, súradnice textúr). Nemôžete preto vytvoriť 2 susedné steny úplne odlišnej farby, pretože ich spoločné vertexy majú rovnakú farbu.
  • textúrovanie je obtiažne. Ako nastavíte súradnice textúry ? Vzniká rovnaký problém ako pro farbe. Pre jednu stenu môžu byť dobré, ale druhej nemusia vyhovovať. Skúste otextúrovať túto kocku! Ak sa to niekomu podarí, môže mi riešenie poslať.
  • svetlá potrebujú normálový vektor. Pre 3 steny so zdieľaným vertexom je aj normálový vektor zdieľaný, čo môže spôsobiť nechcené a nereálne osvetlenie. Tu sa obyčajne dá pomôcť tým, že sa z tých troch normálových vektorov vypočíta akýsi priemer.

Je len a len na vás, kde sa ich rozhodnete používať. Závisí to hlavne od typu scény. Najlepšie je ich využitie pri renderovaní terénu, pretože tam nevzniká problém s textúrovaním. Súradnice tu a tv sa dajú navrhnúť tak, aby trojuholníky presne do seba zapadali. Jeden taký príklad si môžete stiahnuť na tejto stránke.

Samotné vytvorenie, nastavenie a použitie indexov v D3D je veľmi jednoduché. Celý proces je v podstate identický s prácou s vertexami.

Dim IBuffer As Direct3DIndexBuffer8
Dim TerenIndex(35) As Integer

Vidíte, že indexy nie sú nič iné, než premenné typu integer. Ďalej vytvoríme 8 vertexov a uložíme ich do Vertex Bufferu. Ku každému trojuholníku priradíme vertexy pomocou indexov. Priradenie vyzerá nasledovne:

TerenIndex(0) = 0
TerenIndex(1) = 1
TerenIndex(2) = 3

CreateIndexBuffer.

Prvý trojuholník bude tvorený vertexami 0,1 a 3. Potom vytvoríme Index Buffer pomocou funkcie CreateIndexBuffer.

LengthInBytes - veľkosť index bufferu.

Usage - použitie. Zatiaľ žiadne neštandardné.

Format - závisí od typu použitých indexov (16 alebo 32 bitové).

Pool - výber pridelenia pamäte pre Ibuffer.

Set IBuffer = D3DDevice.CreateIndexBuffer(Len(TerenIndex(0)) * 24, 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT) D3DIndexBuffer8SetData IBuffer, 0, Len(TerenIndex(0)) * 24, 0, TerenIndex(0)

Akonáhle je IB vytvorený, naplníme ho indexami:

D3DIndexBuffer8SetData

IBuffer - cieľový IB.

Offset - odkiaľ sa začne zapisovať do IB (v bytoch). 0 znamená od začiatku.

Size - veľkosť IB (v bytoch).

Flags - vlajky pre špeciálny typ zápisu.

Data - pole obsahujúce indexy.

Určite ste si všimli, že je to veľmi podobné vytváraniu a napĺňaniu vertex bufferov. Samozrejme, mohli by sme tento krok vynechať a renderovať priamo z poľa, ale stratíme tým efektívnosť, ktorú D3D buffery ponúkajú. Všetky potrebné informácie pre D3D sme odoslali a teraz sme už pripravený na renderovanie.

D3DDevice.SetStreamSource 0, VBuffer, Len(Teren(0))
D3DDevice.SetIndices IBuffer, 0
D3DDevice.DrawIndexedPrimitive D3DPT_TRIANGLELIST, 0, 24, 0, 8

Pri renderovaní nesmieme zabudnúť určiť, z ktorého vertex bufferu budeme chcieť renderovať. Indexy sa totiž nevzťahujú na žiadny konkrétny VB. Taktiež musíme D3D oznámiť, ktoré indexy sa chystáme použiť a to cez funkciu SetIndices. Zaujímavý je druhý parameter funkcie - BaseVertexIndex. Ak ho nastavíme napr. na 5, bude ku každému indexu pripočítaná hodnota 5. Index, ktorý sa odkazuje na 3 vertex vo Vbuffery sa v skutočnosti bude odkazovať na vertex ôsmy. Význam to má napr. vtedy, ak používate viac VB s jedným IB. Rôzne sady indexov pre rôzne VB môžu byť v jednom buffery. Vždy nastavíte iný BaseVertexIndex pre začiatok novej sady. Nakoniec nasleduje hlavná funkcia DrawIndexedPrimitive.

DrawIndexedPrimitive

PrimitiveType - spôsob spájania vertexov.

MinIndex - plní tú istú úlohu ako BaseVertexIndex v SetIndices.

NumIndices - počet použitých indexov.

StartIndex - ktorým indexu sa začne renderovať (po pripočítaní MinIndex)

PrimitiveCount - koľko trojuholníkov má byť vyrenderovaných.

Pri renderovaní cez indexy sa takisto používa TriangleList, Stip, Fan.

To je všetko, čo by ste mali vedieť o indexoch.

Priložené súbory: