24. září 2013, Brno Připravil: David Procházka Vykreslování grafických primitiv Počítačová grafika 2
Vykreslování grafických primitiv Strana 2 / 38 Obsah přednášky 1 Vykreslování grafických primitiv 2 Nastavení vzhledu bodů 3 Pole vrcholů 4 Vykreslování objektů v polích vrcholů 5 Shrnutí
Vykreslování grafických primitiv Strana 3 / 38 Vykreslování graf. primitiv Objekty jsou definovány jako skupiny vrcholů. Výsledný tvar je otázkou reprezentace těchto vrcholů. 1 glbegin ( typ_primitiva ); 2 glvertex3f (...); 3 glvertex3f (...); 4 glvertex3f (...); 5 glvertex3f (...); 6... 7 glend (); Základní primitiva: GL POINTS, GL LINES, GL LINE STRIP, GL LINE LOOP, GL TRIANGLES, GL TRIANGLE FAN, GL TRIANGLE STRIP, GL QUADS, GL POLYGON, GL QUAD STRIP 1. 1 od verze OpenGL 3.0 jsou tato primitiva označena na zastaralá
Vykreslování grafických primitiv Strana 4 / 38 Typy grafických primitiv
Vykreslování grafických primitiv Strana 5 / 38 Další grafická primitiva Mimo tato primitiva existují varianty se stejnolehlými vrcholy: LINES ADJACENCY, LINE STRIP ADJACENCY, TRIANGLES ADJACENCY, TRIANGLE STRIP ADJACENCY. Tento typ primitiv využívají Vertex Shadery.
Vykreslování grafických primitiv Strana 6 / 38 Vykreslení jednobarevného trojúhelníku 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 4 glcolor3f (1.0, 0.0, 0.0); // definice barvy 5 6 // vykresluj trojuhelniky dokud nebude receno jinak 7 glbegin ( GL_TRIANGLES ); 8 glvertex2i (10, 10); // definice vrcholu 9 glvertex2i (60, 300); 10 glvertex2i (460, 460); 11 // prestan vykreslovat trojuhelniky 12 glend (); 13 14 glflush (); 15 }
Vykreslování grafických primitiv Strana 7 / 38 Vykreslení dvou jednobarevných trojúhelníků 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 4 glcolor3f (1.0, 0.0, 0.0); 5 6 // vykresluj trojuhelniky dokud nebude receno jinak 7 glbegin ( GL_TRIANGLES ); 8 glvertex2i (520, 20); // prvni trojuhelnik 9 glvertex2i (50, 400); 10 glvertex2i (600, 460); 11 glvertex2i (10, 10); // druhy trojuhelnik 12 glvertex2i (60, 300); 13 glvertex2i (460, 420); 14 // prestan vykreslovat trojuhelniky 15 glend (); 16 17 glflush (); 18 }
Vykreslování grafických primitiv Strana 8 / 38 Vykreslení barevného trojúhelníku 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 4 // vykresluj trojuhelniky dokud nebude receno jinak 5 glbegin ( GL_TRIANGLES ); 6 glcolor3f (1.0, 0.0, 0.0); // definice cervene barvy 7 glvertex2i (10, 10); // definice vrcholu 8 glcolor3f (0.0, 1.0, 0.0); // definice zelene barvy 9 glvertex2i (60, 300); 10 glcolor3f (0.0, 0.0, 1.0); // definice modre barvy 11 glvertex2i (460, 460); 12 // prestan vykreslovat trojuhelniky 13 glend (); 14 15 glflush (); 16 }
Vykreslování grafických primitiv Strana 9 / 38 Immediate mode Tento způsob vykreslování objektů (immediate mode) je zastaralý. V nových verzích OpenGL přestane být postupně podporován. Jedná se o příkazy: glbegin a glend, glcolor*, glsecondarycolor*, glvertex*, glindex*, glnormal*, gltexcoord*, glfogcoord*, Jediným zachovávaným je glvertexattrib*.
Nastavení vzhledu bodů Strana 10 / 38 Obsah přednášky 1 Vykreslování grafických primitiv 2 Nastavení vzhledu bodů 3 Pole vrcholů 4 Vykreslování objektů v polích vrcholů 5 Shrnutí
Nastavení vzhledu bodů Strana 11 / 38 Nastavení vzhledu bodů Velikost bodu lze nastavit pomocí glpointsize(). Velikost je v pixelech a nenulová. Výchozí hodnota je 1. V budoucích verzích OpenGL již nebude podporován příkaz pro vyhlazení bodu POINT SMOOTH, ani režim POINT SPRITE. Body budou vždy vykreslovány tak, jako by byl aktivován režim POINT SPRITE (bod je zobrazován jako 2D objekt).
Nastavení vzhledu bodů Strana 12 / 38 Nastavení vzhledu linií Linie může mít specifikovánu šířku gllinewidth(). Šířka musí být menší, než 1.0. V opačném případě je generována chyba INVALID VALUE. Dříve uváděnou vlastností byl vzorek gllinestipple() s přílušnými parametry a následně aktivovaný pomocí glbegin(gl LINE STIPPLE). Bodoucí verze OpenGL však s touto fukcí nepočítají.
Nastavení vzhledu bodů Strana 13 / 38 Nastavení vzhledu polygonů Každý polygon má přední a zadní stranu. V základním nastavení jsou obě strany renderovány stejným způsobem. Pro změnu vykreslování použijeme příkaz glpolygonmode(). Příkaz má dva parametry face může mít hodnotu GL FRONT, GL BACK, GL FRONT AND BACK určuje, zda budou vykreslovány pouze přední, zadní nebo obě strany polygonu. mode určuje způsob za bude polygon vykreslen body, úsečkami nebo s výplní GL POINT, GL LINE, GL FILL.
Nastavení vzhledu bodů Strana 14 / 38 Nastavení vzhledu polygonů (2) V budoucích verzích OpenGL se počítá s odstranění face. Obě strany budou vždy renderovány stejně. Stejně tak se předpokládá vypuštění příkazu glpolygonstipple().
Pole vrcholů Strana 15 / 38 Obsah přednášky 1 Vykreslování grafických primitiv 2 Nastavení vzhledu bodů 3 Pole vrcholů 4 Vykreslování objektů v polích vrcholů 5 Shrnutí
Pole vrcholů Strana 16 / 38 Zásadní problémy ukázaných příkladů Každá definice barvy a vrcholu znamená volání funkce. Je nutné omezit neustálé volání funkcí. Je nutné omezit duplicitní definice vrcholů (jeden vrchol je použit několikrát v různých objektech). Řeší se pomocí display listů nebo polí vrcholů (Vertex Buffers).
Pole vrcholů Strana 17 / 38 Vertex Buffers pole vrcholů Vertex buffers představují alternativu k definování objektů pomocí samostatných vrcholů. Tato metoda je rychlejší (není nutné volat tolik funkcí) a prostorově úspornější (není nutné duplicitně definovat vrcholy). Pro použití pole vrcholů je nutné provést následující kroky: 1 Aktivace pole/polí kromě pole vrcholů lze definovat i pole barev, sekundárních barev, souřadnic textur, aj. 2 uložení dat do polí pomocí ukazatelů, 3 vykreslení elementů definovaných poli.
Pole vrcholů Strana 18 / 38 Aktivace pole Pole aktivujeme a deaktivujeme příkazy: glenableclientstate(gl... ARRAY) a gldisableclientstate(gl... ARRAY). K dispozici jsou následující pole: GL VERTEX ARRAY pole souřadnic vrcholů, GL COLOR ARRAY pole složek barev, GL SECONDARY COLOR ARRAY pole sekundárních barev, GL INDEX ARRAY složky indexovaných bar. (zastaralé) GL NORMAL ARRAY hodnoty normál (výpočet osvětlení), GL FOG COORDINATE ARRAY pole pro práci s mlhou, GL TEXTURE COORD ARRAY pole souřadnic do textury, GL EDGE FLAG ARRAY příznaky pro hrany (zda je viditelná).
Pole vrcholů Strana 19 / 38 Uložení dat o trojúhelníku do pole Pole aktivujeme a deaktivujeme příkazy: Za předpokladu, že vrcholy trojúhelníku jsou dány dvěma souřadnicemi typu GLint (x a y), bude pole: {x 1, y 1, x 2, y 2, x 3, y 3 }, kde x a, y a jsou hodnoty typu GLint. V C++ to lze zapsat: GLint vertices[] = {10, 10, 100, 300, 200, 10}; Dále je nezbytné specifikovat strukturu pole. K tomu slouží: glvertexpointer() (definice struktury vrcholů), glcolorpointer() (definice barevných složek).
Pole vrcholů Strana 20 / 38 Ukazatele do pole vrcholů glvertexpointer(glint size, GLenum type, GLsizei stride, const GLvoid *pointers) size nabývá hodnot 2, 3, 4 podle počtu souřadnic vrcholu, type specifikuje typ souřadnic pole vrcholů (GL SHORT, GL INT, GL FLOAT, GL DOUBLE), stride určuje vzdálenost mezi dvěma po sobě jdoucími prvky v bytech (podrobně zmíněno u prokládaných polí) Příklady: pointers obsahuje název pole s definicí vrcholů. glvertexpointer(2, GL INT, 0, vertices); glvertexpointer(2, GL FLOAT, 5*sizeof(GL FLOAT), &triangle[0]);
Pole vrcholů Strana 21 / 38 Ukazatele do pole barev glcolorpointer(glint size, GLenum type, GLsizei stride, cont GLvoid *pointers) Parametry mají obdobný význam jako u pole vrcholů. size nabývá hodnot 3 nebo 4 (bez/s alfa kanálem) type může mít mimo hodnoty zmíněné u pole vrcholů také hodnoty GL BYTE, GL UNSIGNED BYTE, GL UNSIGNED SHORT, GL UNSIGNED INT.
Vykreslování objektů v polích vrcholů Strana 22 / 38 Obsah přednášky 1 Vykreslování grafických primitiv 2 Nastavení vzhledu bodů 3 Pole vrcholů 4 Vykreslování objektů v polích vrcholů 5 Shrnutí
Vykreslování objektů v polích vrcholů Strana 23 / 38 Efektivnější vykreslení hodnot v poli Existuje příkaz glarrayelement(glint poradi), kde parametr pořadí určuje o kolikátý vrchol ze seznamu se jedná (viz předcházející příklady). Tento příkaz tedy nahrazuje dvojci příkazů glvertex* a glcolor* (snížíme počet volání až na polovinu).
Vykreslování objektů v polích vrcholů Strana 24 / 38 Samostatná pole vrcholů 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 static GLint vertices [] = // tri dvojce souradnic 4 {10, 10, 100, 300, 200, 10}; 5 static GLfloat colors [] = // tri trojce barev 6 {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0}; 7 8 glenableclientstate ( GL_VERTEX_ARRAY ); 9 glenableclientstate ( GL_COLOR_ARRAY ); 10 glvertexpointer (2, GL_INT, 0, vertices ); 11 glcolorpointer (3, GL_FLOAT, 0, colors ); 12 13 glbegin ( GL_TRIANGLES ); 14 glarrayelement (0); 15 glarrayelement (1); 16 glarrayelement (2); 17 glend (); 18 19 gldisableclientstate ( GL_VERTEX_ARRAY ); 20 gldisableclientstate ( GL_COLOR_ARRAY ); 21 glflush ();
Vykreslování objektů v polích vrcholů Strana 25 / 38 Kombinované pole stride a pointers stride má v případě použití samostatných polí pro vrcholy, barvy, atp. hodnotu 0. Nenulovou hodnotu má, když je do jednoho pole ukládáno více různých definic (např. barvy i souřadnice). Pak je hodnota rovna vzdálenosti v bytech mezi začátky dvou po sobě jdoucích hodnot. Např.: pokud barvy i vrcholy jsou typu GL FLOAT, pak vzdálenost bude 5*sizeof(GL FLOAT) (2 souřadnice pro vrcholy + 3 barevné složky). Dále je v tomto případě nutné posledním parametrem pointers definovat, kde pole začíná. V případě, že v poli jsou hodnoty uloženy ve formátu x 1, y 1, R 1, G 1, B 1,... bude pointers pro vrcholy &kombinovanepole[0] a pro barvy &kombinovanepole[2].
Vykreslování objektů v polích vrcholů Strana 26 / 38 Kombinované pole vrcholů 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 static GLfloat triangle [] = { 4 10.0, 10.0, 1.0, 0.0, 0.0, // 2 sour. vrch., 3 bar. slozky 5 100.0, 300.0, 0.0, 0.0, 1.0, 6 200.0, 10.0, 0.0, 1.0, 0.0}; 7 8 glenableclientstate ( GL_VERTEX_ARRAY ); 9 glenableclientstate ( GL_COLOR_ARRAY ); 10 glvertexpointer (2, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangle [0]); 11 glcolorpointer (3, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangle [2]); 12 13 glbegin ( GL_TRIANGLES ); 14 glarrayelement (0); // prikaz je popsan nize 15 glarrayelement (1); 16 glarrayelement (2); 17 glend (); 18 19 gldisableclientstate ( GL_VERTEX_ARRAY ); 20 gldisableclientstate ( GL_COLOR_ARRAY ); 21 glflush ();
Vykreslování objektů v polích vrcholů Strana 27 / 38 Kritika prezentovaného přístupu Ani tento způsob vykreslování objektů není z hlediska dopředné kompatibility s novými verzemi OpenGL vhodný, protože se stále používají příkazy glbegin(), glend(), které budou ze specifikace odstraněny.
Vykreslování objektů v polích vrcholů Strana 28 / 38 Efektivní vykreslení vrcholů gldrawelements(glenum mode, Glsizei count, GLenum type, void* indices) Umožňuje vykreslení objektu pomocí jediného volání. Nahrazuje celou strukturu nacházející se mezi glbegin(*) a glend(). mode typ vykreslovaného objektu (např. GL TRINAGLES), count počet vrcholů, které jsou uloženy v poli indexů (tj. počet vykreslovaných vrcholů), type typ indexů v poli indexů (např. GL INT), indices odkaz na pole indexů. Pole indexů umožňuje vybrat z pole vrcholů seznam vrcholů, které budou vykresleny. Nejedná se tedy přímo o pole vrcholů!
Vykreslování objektů v polích vrcholů Strana 29 / 38 Efektivní vykreslení vrcholů příklad 1 void display ( void ){ 2 glclear ( GL_COLOR_BUFFER_BIT ); 3 static GLfloat triangle [] = { 4 10.0, 10.0, 1.0, 0.0, 0.0, 5 100.0, 300.0, 0.0, 0.0, 1.0, 6 200.0, 10.0, 0.0, 1.0, 0.0}; 7 8 glenableclientstate ( GL_VERTEX_ARRAY ); 9 glenableclientstate ( GL_COLOR_ARRAY ); 10 11 glvertexpointer (2, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangle [0]); 12 glcolorpointer (3, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangle [2]); 13 14 static GLubyte indices []={0,1,2}; // definice pole indexu 15 gldrawelements ( GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, indices ); 16 17 gldisableclientstate ( GL_VERTEX_ARRAY ); 18 gldisableclientstate ( GL_COLOR_ARRAY ); 19 glflush (); 20 }
Vykreslování objektů v polích vrcholů Strana 30 / 38 Rozšíření gldrawelements() glmultidrawelements(glenum mode, GLsizei* count, GLenum type, void** indices, GLsizei primcount) Umožňuje předat více polí pro vykreslení. 1... 2 static GLubyte firstindices [] = {0, 1, 2}; 3 static GLubyte secondindices [] = {2, 4, 8}; 4 static GLsizei count [] = {3, 3}; 5 static GLvoid * indices [2] = { firstindices, secondindices }; 6 7 glmultidrawelements ( 8 GL_LINE_STRIP, // typ vykreslovanych primitiv 9 count, // pole s pocty indexu v polich 10 GL_UNSIGNED_BYTE, // typ indexu 11 indices, // pole s poli indexu 12 2); // pocet poli 13...
Vykreslování objektů v polích vrcholů Strana 31 / 38 Rozšíření gldrawelements() (2) 2 gldrawrangeelements(glenum mode, GLuint begin, GLuint end, GLsizei count, GLenum type, void* indices) Umožňuje definovat rozsah indexů vrcholů, které budou použity. Všechny hodnoty v poli indexů by měly být v rozmezí begin, end. Hodnoty ležící v rozsahu daném hranicemi, budou optimalizovány pro rychlejší vykreslení. Pokud nejsou, může OpenGL vyhlásit chybu (ale nemusí, záleží na implementaci). 2 nezkouším
Vykreslování objektů v polích vrcholů Strana 32 / 38 Rozsahy gldrawrangeelements() 3 Tento příkaz má smysl zejména v kombinaci s příkazy: glgetintegerv(gl MAX ELEMENTS VERTICES), glgetintegerv(gl MAX ELEMENTS INDICES). Ty jsou schopny vrátit maximální doporučený počet vrcholů, resp. indexů. Pokud 1 end-start+1 > glgetintegerv(gl MAX ELEMENTS VERTICES) 2 nebo count > glgetintegerv(gl MAX ELEMENTS INDICES), může dojít ke snížení výkonu vykreslování. 3 nezkouším
Vykreslování objektů v polích vrcholů Strana 33 / 38 Přímé vykreslování polí gldrawarrays(glenum type, GLint first, GLsizei count), glmutidrawarrays(glenum type, GLint* first, GLsizei* count, GLsizei primcount) Nepracují s indexy, ale přímo vykreslují pole vrcholů. Od vrcholu specifikovaného pomocí first, po vrchol first + count.
Vykreslování objektů v polích vrcholů Strana 34 / 38 Vykreslení barevných trojúhelníků pomocí funkce gldrawarrays() 1 void display ( void ){ 2 // zde bude vymazani frame bufferu, 3 // definice pole, zapnuti poli barev a vrcholu... 4 5 glvertexpointer (2, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangles [0]); 6 glcolorpointer (3, GL_FLOAT, 5* sizeof ( GL_FLOAT ), & triangles [2]); 7 8 gldrawarrays ( GL_TRIANGLES, 0, 6); 9 10 // vypnuti poli 11 glflush (); 12 }
Vykreslování objektů v polích vrcholů Strana 35 / 38 Srovnání metod vykreslování Nedoporučené metody vykreslování prvků: glarrayelement nahrazuje jen definici vrcholu. Doporučené metody vykreslování prvků: gldrawelements přebírá indexy do pole, glmultidrawelements přebírá více polí indexů do pole, gldrawrangeelements vykresluje rozsah indexů do pole, gldrawarrays přebírá přímo pole a vykresluje rozsah, glmutidrawarrays přebírá několik polí, glinterleavedarrays přebírá prokládané pole (viz dále).
Shrnutí Strana 36 / 38 Obsah přednášky 1 Vykreslování grafických primitiv 2 Nastavení vzhledu bodů 3 Pole vrcholů 4 Vykreslování objektů v polích vrcholů 5 Shrnutí
Shrnutí Strana 37 / 38 Shrnutí Bylo předvedeno, jaká jsou základní primitiva a jejich vlastnosti. Bylo zmíněno vykreslování pomocí jednotlivých vrcholů a negativa této metody. Bylo doporučeno řešení v podobě ukládání dat do polí a následné vykreslování pomocí příkazů gl*elements a gl*arrays. Pokročilou verzí zmíněného vykreslování je použití polí vrcholů v objektech bufferů (Vertex Buffer Object), které bude vysvětleno dále.
Shrnutí Strana 38 / 38 Kontrolní otázky/úkoly Uložte informace o vrcholech dvou čtverců do pole a následně je vykreslete. Pokud nemáte použít GL QUAD* nebo GL POLYGON, jak je možné je efektivně vykreslit? Zkuste uložit informace o vrcholech a barvách do jediného pole.