Mai agymenésem a vertexenként elküldött adatmennyiség csökkentéséről szól. Ezen adatokat -az új terminológia alapján- vertex attribútumoknak hívjuk, amelyeket 4 db lebegőpontos számnégyes reprezentálja és legalább 9 db van belőlük. Míg a régi terminológiában minden egyes attribútum szerepe és neve meghatározott volt, az újban már csak index jelzi őket. Ezek az alábbiak:
pozíció | mindenképp szükséges ennek megléte, ez a renderelés alapja! | 0 |
súly | hardveres skinning paraméterei | 1 |
normál | a vertex normál vektora | 2 |
elsődleges szín | texture environmentben felhasznált szín | 3 |
másodlagos szín | color sumban felhasznált szín | 4 |
köd koordináta | volumetrikus köd számításkor használt adat | 5 |
- | - | 6 |
- | - | 7 |
textúra koordináta | a textúra mintavételezéshez felhasznált adat | 8 |
Megjegyzendő, hogy textúra koordinátákból annyi darab lehetséges, ahány texturázó egység elérhető.
A táblázatból látható tehát, hogy vertexenként 9*4 adatot tudunk elküldeni a gpunak, amiből 4-t mindig kötelező elküldenünk. Természetesen minél több adatot küldünk vertexenként annál lassabb futásra számíthatunk hiszen
- az adatot el kell juttatni a vertex feldolgozónak
- a vertex feldolgozónak el kell végeznie a szükséges műveleteket
ezért törekednünk kell ezek mennyiségének csökkentésére. Erre többféle módszer kínálkozik.
Az első esetben legegyszerűbb, ha csökkentjük a kirajzolandó háromszögek mennyiségét - low poly modellek használata - azonban ez jelentős mértékű minőségromláshoz vezethet.
Hatékonyabb módszer a háromszögek szalaggá történő rendezése, amikor a háromszögek számát nem csökkentjük csak a kirajzolásukhoz szükséges vertexek számát probáljuk meg csökkenteni.
Bizonyos esetekben még tovább csökkenthetjük az adataink számát
- ha "becsomagoljuk" őket. Ehhez viszont szükséges a vertex program megléte, amellyel a kicsomagolást el tudjuk végezni. Például: vertexenként elküldünk egy pozíciót (xyz) egy színt (rgb) és egy textúra koordinátát(st). Ez összesen 8 db számot jelent vagyis ez a 3 adat pontosan elfér 2 attribútumban három helyett! A kitétel csak annyi, hogy a 0. attribútumot mindenképp használnunk kell, de hogy melyik adatot hova és hogyan pakoljuk az már tőlünk függ.
- ha csökkentjük a bitek számát, amelyen tároljuk az adatainkat. Például: a vertex pozíció néha elég shorton (2byte) tárolni, de a -1.0...1.0 ill. 0.0....1.0 tartományba eső adatok tárolására sokszor elegendő egy byte is!
A második eset optimalizálására maga a gpu kínál fel egy lehetőséget ún. vertex cache néven. Működése a vertexindexeken alapul vagyis csak indexelt vertexek renderelése esetén kerül sor a felhasználására. A gpu a vertex cache-ben képes bizonyos számú, már feldolgozott vertexet az indexek alapján tárolni és ha ismételten ugyanolyan indexű vertexet küldünk el a gpunak akkor az itt tárolt adatot fogja újra felhasználni megspórolva a feldolgozást.
Természetesen a vertexindexek megfelelő sorbarendezésével mi is sokat tehetünk a vertex cache optimális kihasználása érdekében - megtehetjük ezt akár háromszög szalaggal is és így nemcsak a vertexek számát, hanem azok feldolgozásához időt is csökkentjük, de optimalizált háromszög lista is alkalmas e célra.
Tudomásom szerint még öt hardver szintű vertex optimalizálási technika létezik.
- Az első az ún. vertex buffer object, amikor minden statikus információt (vertexek és vertexindexek) feltöltünk a video memóriába így ezen adatok elérésének ideje drasztikusan lerövidül. Animált, dinamikusan változó vertex adatok esetén javasolt a dupla bufferelt vbo. Ilyenkor 2 vbot tartunk fenn a renderelés számára: az egyikbe beírjuk a friss adatokat, a másikból renderelünk majd a következő frameben felcseréljük a 2 vbot.
- A vertex adatok átküldését optimalizálhatja a draw_range_elements, amely a függvénnyel megadott indexeken kívül eső vertexeket nem küldi el a gpunak.
- A compiled_vertex_array esetén az adott vertex tömböt lezárjuk (lock) így azokat vagy a feldolgozott eredményeket a gpu "compile"-olni(?) tudja.
- Néhány esetben előfordulhat, hogy ugyanazzal a vertex tömbbel, több geometriát is akarunk renderelni. Erre az esetre készült a multi_draw_arrays.
- Instanced geometry, amelyet viszont még nem használtam...
Nem szabad azonban elfelejtenünk, hogy a vertex optimalizálás legalapvetőbb módszere a csak látható elemek renderelése (frustum cull, occlusion cull stb)!