´ r´ı 2013, Brno 30. zaˇ ´ Pˇripravil: David Prochazka
Vertex Buffer Objects ˇ ıtacov ˇ a´ grafika 2 Poc´
ˇ Obsah pˇredna´ sky
ˇ Obsah pˇredna´ sky 1
´ sky Obsah pˇrednaˇ
2
Vertex Buffer Objects
3
Pˇr´ıklady
4
Shrnut´ı
Strana 2 / 22
ˇ Obsah pˇredna´ sky
Strana 3 / 22
ˇ Obsah pˇredna´ sky ´ an´ ´ ı informac´ı o vrcholech a jejich vlastnostech do pameti ˇ Uklad ´ ı. graficke´ karty za uˇ ´ celem efektivn´ıho vykreslovan´
Vertex Buffer Objects
ˇ Obsah pˇredna´ sky 1
´ sky Obsah pˇrednaˇ
2
Vertex Buffer Objects
3
Pˇr´ıklady
4
Shrnut´ı
Strana 4 / 22
Vertex Buffer Objects
Strana 5 / 22
ˇ ı graficka´ primitiva Dals´ ´ Vertex Buffer Objects (VBO) lze volneˇ pˇrekladat jako objekty pro buffery vrcholu. ˚ ´ ´ vykreslovan´ ´ ı Zasadn´ ı rozd´ıl oproti pˇredchoz´ım metodam ´ ame ´ spoˇc´ıva´ v tom, zˇ e v tomto pˇr´ıpadeˇ uklad data pro ´ ı pˇr´ımo pameti ˇ graficke´ karty. vykreslovan´ Tam k nim obvykle opakovaneˇ pˇristupujeme. ´ ı sceny ´ tedy nen´ı nutne´ pˇrenaˇ ´ set data Pˇri pˇrekreslovan´ ´ z operaˇcn´ı pameti ˇ do pameti ˇ graficke´ karty. neustale ´ ı VBO je doporuˇcovana´ metoda pro vykreslovan´ ´ ı Vyuˇz´ıvan´ podle nov´ych verz´ı specifikace OpenGL (3.0+).
Vertex Buffer Objects
Strana 6 / 22
´ ı do VBO se sklad ´ a´ z peti ˇ kroku˚ Vykreslovan´ 1
´ ı jmena ´ Vygenerovan´ pro buffer,
2
aktivace bufferu (bind),
3
uloˇzen´ı dat do bufferu,
4
´ ı, vyuˇzit´ı bufferu pro vykreslovan´ ˇ zruˇsen´ı bufferu z pameti.
5
Vertex Buffer Objects
Strana 7 / 22
´ ı jmena ´ Vygenerovan´ bufferu glGenBuffers(GLsizei n, GLuint *buffers). ´ ´ u˚ pro buffery Funkci pˇredame v parametru n kolik nazv potˇrebujeme vygenerovat. ´ Vygenerovane´ nazvy se uloˇz´ı do pole buffers. ´ u. Pole bude obsahovat sekvenci celoˇc´ıseln´ych nazv ˚ ´ Funkce zaruˇcuje, zˇ e tyto nazvy nebyly dˇr´ıve pouˇzity a ´ proto mohou slouˇzit jako jednoznaˇcn´y identifikator bufferu. ´ ı jmena ´ Pˇr´ıklad ilustruje vygenerovan´ pro jeden buffer. 1 2
GLuint bufferID ; glGenBuffers (1 , & bufferID );
ˇ ı bufferu s dan´ym jmenem ´ Uvolnen´ provedeme pomoc´ı funkce glDeleteBuffers(): 1
glDeleteBuffers (1 , & bufferID );
Vertex Buffer Objects
Strana 8 / 22
Vytvoˇren´ı bufferu ˇ graficke´ karty. Vytvoˇr´ıme fyzicky buffer v pameti void glBindBuffer(GLenum target, GLuint buffer). ´ buffer – nazev bufferu, kter´y jsme vygenerovali v pˇredchoz´ım kroku. ˇ bude ukladat ´ target – identifikuje typ bufferu (co se do nej za hodnoty). Muˇ ˚ ze nab´yvat hodnot: ´ an´ ´ ı vrcholu˚ objektu, GL ARRAY BUFFER – slouˇz´ı pro uklad ˚ ´ an´ ´ ı indexu˚ na GL ELEMENT ARRAY BUFFER – slouˇz´ı pro uklad vrcholy, GL PIXEL PACK BUFFER, GL PIXEL UNPACK BUFFER – slouˇz´ı ´ an´ ´ ı pixelu˚ rastru˚ (nyn´ı nas ´ nezaj´ıma). ´ pro uklad
Pˇr´ıklad: 1
glBindBuffer ( GL_ARRAY_BUFFER , bufferID )
Vertex Buffer Objects
Strana 9 / 22
ˇ ı bufferu Naplnen´ void glBufferData(GLenum target, GLsizeiptr size, const GLvoid data, GLenum usage) ˇ identifikuje typ bufferu, target – opet size – obsahuje velikost dat kop´ırovan´ych do bufferu, data – obsahuje ukazatel na pole vrcholu, ˚ ktere´ ma´ b´yt do ´ bufferu kop´ırovano, usage – popisuje zpusob pouˇzit´ı bufferu. ˚ ˇ Lze pouˇz´ıvat libovolne. Jen za uˇ ´ celem optimalizace v´ykonu. ˇ nebude to m´ıt vliv na Pokud parametr zvol´ıte nevhodne, ˇ jej´ı v´ykon. Parametr funkˇcnost aplikace, ale bude ovlivnen ´ ˇ do tˇr´ı skupin: nab´yva´ nasleduj´ ıc´ıch hodnot, ktere´ lze rozdelit 1 2 3
GL STREAM DRAW, GL STREAM READ, GL STREAM COPY, GL STATIC DRAW, GL STATIC READ, GL STATIC COPY, GL DYNAMIC DRAW, GL DYNAMIC READ, GL DYNAMIC COPY.
Vertex Buffer Objects
Strana 10 / 22
ˇ ı bufferu – vyznamy Naplnen´ ´ parametru˚ ˇ Parametry pro cetnost pˇr´ıstupu do bufferu Parametr V´yznam ´ ˇ ´ STREAM data budou zapsana jednou a cˇ tena jen nekolikr at ´ ´ STATIC data budou zapsana jednou a cˇ tena mnohokrat ˇ ´ ´ DYNAMIC data budou ctena i zapisovana mnohokrat Parametry pro zpusob ˚ pˇr´ıstupu do bufferu Parametr V´yznam ´ aplikac´ı DRAW obsah bufferu bude zapsan ´ pro renderovan´ ´ ı pomoc´ı OpenGL a pouˇz´ıvan ´ aplikac´ı READ obsah bude vytvoˇren OpenGL a vyuˇz´ıvan ´ COPY obsah bude vytvoˇren OpenGL a nasledn eˇ OpenGL ´ pro renderovan´ ´ ı vyuˇz´ıvan
Vertex Buffer Objects
Strana 11 / 22
ˇ ı bufferu – pˇr´ıklad Naplnen´ ˇ ı bufferu souˇradnicemi vrcholu˚ z pole Pˇr´ıklad naplnen´ trinagles: 1 2 3 4 5
glBufferData ( GL_ARRAY_BUFFER , sizeof ( triangles ) , triangles , GL_STATIC_DRAW );
// // // //
typ bufferu kolik dat ukladam odkud pouziti bufferu
´ pˇr´ıkaz glBufferData() na buffer, kter´y jiˇz Pokud zavolate ´ data obsahuje budou pˇredchoz´ı data smazany. ˇ s´ı mnoˇzstv´ı dat, neˇz je Pokud se pokus´ıte uloˇzit vetˇ ´ eˇ volne´ m´ısto v pameti ˇ graficke´ karty, bude aktualn vyhozena chyba GL OUT OF MEMORY.
Vertex Buffer Objects
Strana 12 / 22
ˇ ı bufferu – oddelen ˇ Naplnen´ a´ inicializace ´ Druhou variantou je inicializovat buffer jako prazdn´ y. Data pak pˇrepsat poˇzadovan´ymi hodnotami. ˇ ˇ s´ı. Nekter e´ zdroje tento zpusob doporuˇcuj´ı jako efektivnejˇ ˚ ˇ ı dat pouˇzijeme napˇr. pˇr´ıkaz K doplnen´ void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data). ˇ udav ´ a´ typ bufferu, druh´y – offset – Prvn´ı parametr opet ´ et ˇ zapis ´ odkud se ma´ do bufferu provad (nula znamena´ od ´ poˇcatku bufferu), tˇret´ı velikost zapisovan´ych dat a posledn´ı je odkaz na data. ´ ı celeho ´ Pˇr´ıklad pˇrepsan´ bufferu: 1
glBufferData(GL ARRAY BUFFER, sizeof(triangles), NULL, GL STATIC DRAW); 2 glBufferSubData(GL ARRAY BUFFER, 0, sizeof(triangles), triangles);
Vertex Buffer Objects
Strana 13 / 22
Definice ukazatele Nyn´ı je nutne´ definovat ukazatel do pole vrcholu, ˚ abychom mohli vykreslovat. ˇ a´ chyba. Toto je krok ve ktere´ se velmi snadno udel Definice je prakticky totoˇzna´ s definic´ı, kterou jsme pouˇz´ıvali u pol´ı vrcholu. ˚ Rod´ıl je pouze posledn´ım parametru – odkaz na pole je roven nule! ´ eˇ vytvoˇren´y buffer a OpenGL automaticky pouˇzije prav ˇ ˇ ukazatel nasmeruje do nej. Pˇr´ıklad: glVertexPointer(2, GL INT, 0, 0); ´ aby pˇr´ıkaz glVertexPointer Z tohoto duvodu je nezbytne, ˚ ´ bezprostˇredneˇ po vytvoˇren´ı bufferu. byl volan
Vertex Buffer Objects
Strana 14 / 22
Aktualizace dat v bufferu ˇ ym glBufferSubData(). Jiˇz zm´ınen´ V pˇr´ıpadeˇ nekorektn´ıch parametru˚ (size je menˇs´ı neˇz ˇ s´ı, neˇz puvodn´ nula, size+offset je vetˇ ı velikost) generuje ˚ chybu GL INVALID VALUE. GLvoid* glMapBuffer(GLenum target, GLenum acess) target – GL ARRAY BUFFER nebo GL ELEMENT ARRAY BUFFER. acess – GL READ ONLY, GL WRITE nebo GL READ WRITE.
´ Pokud buffer nelze namapovat, je vracena chyba GL OUT OF MEMORY. ´ ı jiˇz namapovaneho ´ Pˇri snaze o namapovan´ bufferu je ´ vracena chyba GL INVALID OPERATION. ´ı V obou pˇr´ıpadech nav´ıc pˇr´ıkaz glMapBuffer() vrat´ hodnotu NULL. ˇ ı bufferu: glUnmapBuffer(GLenum target). Uvolnen´
Pˇr´ıklady
ˇ Obsah pˇredna´ sky 1
´ sky Obsah pˇrednaˇ
2
Vertex Buffer Objects
3
Pˇr´ıklady
4
Shrnut´ı
Strana 15 / 22
Pˇr´ıklady
VBO pˇr´ıklad – inicializace 1 2
GLuint vertexID ; // identifikatory bufferu GLuint colorID ;
3 4 5 6 7 8 9
void init ( void ) { glClearColor (0.0 , 0.0 , 0.0 , 0.0); glMatrixMode ( GL_PROJECTION ); glLoadIdentity (); gluOrtho2D (0 , 640 , 0 , 480);
10
// vygenerovani cisel pro ID bufferu glGenBuffers (1 , & vertexID ); glGenBuffers (1 , & colorID );
11 12 13 14
}
Strana 16 / 22
Pˇr´ıklady
VBO pˇr´ıklad – definice vrcholu 1 2
void display ( void ){ glClear ( G L_ C O LO R _ BU F F ER _ B IT );
3 4 5 6 7 8 9
// definice vrcholu a barev GLint triangles [] = { 10 , 10 , 320 , 470 , 630 , 10 , };
10 11 12 13 14 15 16
GLfloat colors [] = { 1.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.0 , 0.0 , 0.0 , 1.0 }; // pokracovani funkce na dalsim slidu
Strana 17 / 22
Pˇr´ıklady
Strana 18 / 22
VBO pˇr´ıklad – vytvoˇren´ı bufferu˚ 1 2 3 4 5
// propojeni jmena bufferu a jeho typu glBindBuffer ( GL_ARRAY_BUFFER , vertexID ); // vytvoreni bufferu a naplneni polem vrcholu glBufferData ( GL_ARRAY_BUFFER , sizeof ( triangles ) , triangles , GL_STATIC_DRAW );
6 7 8 9
// nastaveni ukazatele na barvy do bufferu // musi byt volano bezprostredne po vytvoreni glVertexPointer (2 , GL_INT , 0 , 0);
10 11 12 13 14
glBindBuffer ( GL_ARRAY_BUFFER , colorID ); glBufferData ( GL_ARRAY_BUFFER , 3* sizeof ( colors ) , colors , GL_STATIC_DRAW ); glColorPointer (3 , GL_FLOAT , 0 , 0);
15 16
// pokracovani funkce na dalsim slidu
Pˇr´ıklady
VBO pˇr´ıklad – aktivace a vykreslen´ı // aktivace pole vrcholu a barev glEn a b le C l ie n t St a t e ( GL_VERTEX_ARRAY ); glEn a b le C l ie n t St a t e ( GL_COLOR_ARRAY );
1 2 3 4
// vykresleni 3 vrcholu trojuhelniku glDrawArrays ( GL_TRIANGLES , 0 , 3);
5 6 7
// zruseni poli glDi s a b l e C l i e n t S t a t e ( GL_COLOR_ARRAY ); glDi s a b l e C l i e n t S t a t e ( GL_VERTEX_ARRAY ); glFlush ();
8 9 10 11 12
}
Strana 19 / 22
Shrnut´ı
ˇ Obsah pˇredna´ sky 1
´ sky Obsah pˇrednaˇ
2
Vertex Buffer Objects
3
Pˇr´ıklady
4
Shrnut´ı
Strana 20 / 22
Shrnut´ı
Strana 21 / 22
Shrnut´ı ´ an´ ´ ı dat, ktera´ je doporuˇcovana ´ VBO jsou metodou uklad jako hlavn´ı metoda v OpenGL od verze 3. ´ an´ ´ ı dat pˇr´ımo do pameti ˇ graficke´ karty. Jedna´ se o uklad ´ a´ z nasleduj´ ´ Pouˇzit´ı vrcholu˚ se sklad ıc´ıch kroku, ˚ ktere´ je ´ nutne´ znat: ´ ı jmena ´ Vygenerovan´ pro buffer, aktivace bufferu (bind), uloˇzen´ı dat do bufferu, 4 vyuˇ ´ ı, zit´ı bufferu pro vykreslovan´ 5 zruˇ ˇ sen´ı bufferu z pameti. 1 2 3
Shrnut´ı
Strana 22 / 22
´ Kontroln´ı otazky/ ukoly ´ ´ auta za Vytvoˇrte pˇr´ıklad, kter´y umoˇzn´ı vykreslen´ı jednoducheho ´ pomoci VBO. Dbejte na korektn´ı objektov´y navrh aplikace. ˇ na hlaviˇckove´ a implementaˇcn´ı soubory v Aplikaci rozdelte ´ ´ souladu s prezentovan´ymi principy objektoveho navrhu.