Hardware pro počítačovou grafiku NPGR019 Geometry & tessellation shaders Jan Horáček http://cgg.mff.cuni.cz/ MFF UK Praha 2012 Jan Horáček Geometry & Tesselation 1 / 42
Obsah Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva 1 2 3 4 Jan Horáček Geometry & Tesselation 2 / 42
Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva Propojení vertex shaderu s geometrickými daty vertexová data (pozice, tex. koordináty, normály... ) vstupují do OpenGL pipeline přes vertex shader je nutné spojit zdroj vertexových dat s proměnnou v shaderu proto je potřeba znát pozici atributu pozice atributu může být explicitně definovaná použitím kvalifikátoru layout explicitně definovaná funkcí glbindattriblocation() zjištěna automatická pozice voláním glgetattriblocation() Jan Horáček Geometry & Tesselation 3 / 42
Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva Propojení vertex shaderu s geometrickými daty data v oddělených částech VBO data jednoho typu spojitě jako pole #define BUFFER_OFFSET(addr) ((GLvoid*) (addr)) GLsizeiptr offset = 0; glvertexattribpointer( vpos, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset) ); offset += sizeof(v); glvertexattribpointer( vcolor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, BUFFER_OFFSET(offset) ); offset += sizeof(c); glvertexattribpointer( vtexcoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset) ); Jan Horáček Geometry & Tesselation 4 / 42
Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva Propojení vertex shaderu s geometrickými daty data prokládána ve VBO data jako struktury ve VBO GLsizei stride = sizeof( VertexData ); GLsizeiptr offset = 0; struct VertexData { GLfloat tc[2]; GLubyte c[4]; GLfloat v[3]; } glvertexattribpointer( vtexcoord, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset) ); offset += sizeof(v.tc); glvertexattribpointer( vcolor, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset) ); offset += sizeof(v.c); glvertexattribpointer( vpos, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset) ); Jan Horáček Geometry & Tesselation 5 / 42
Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva Propojení vertex shaderu s geometrickými daty je potřeba oznámit OpenGL, která vertexová pole budou použita glenablevertexattribarray( vpos ); glenablevertexattribarray( vcolor ); glenablevertexattribarray( vtexcoord ); Jan Horáček Geometry & Tesselation 6 / 42
Vykreslování geometrických primitiv Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva pro spojité pole vertexů (po částech i prokládané) gldrawarrays( GL_TRIANGLE_STRIP, 0, n ); 0 v c tc 1 2 v c tc v c tc 1 3 5 3 v c tc 4 v c tc 0 2 4 5 v c tc Jan Horáček Geometry & Tesselation 7 / 42
Vykreslování geometrických primitiv Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva pro indexované skupiny vertexů gldrawelements( GL_TRIANGLE_STRIP, n, GL_UNSIGNED_SHORT, BUFFER_OFFSET(offset) ); 0 v c tc 1 v c tc 2 v c tc 3 v c tc 4 v c tc 5 v c tc 0 1 2 3 1 15 3 16 15 16 17 1 3 5 0 2 4 Jan Horáček Geometry & Tesselation 8 / 42
Instancované vykreslování Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva posílání vícekrát stejné geometrie do OpenGL každá iterace je nová instance vertex shader může měnit vykreslování v závislosti na tom, která instance se zrovna vykresluje číslo iterace uloženo v GLSL proměnné gl_instanceid gldrawarraysinstanced( GL_TRIANGLE_STRIP, 0, n, 10 ); gldrawelementsinstanced( GL_TRIANGLE_STRIP, n, GL_UNSIGNED_INT, BUFFER_OFFSET(0), 10 ); Jan Horáček Geometry & Tesselation 9 / 42
Variace na gldrawelements() Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva občas se hodí přidat offset k seznamu vykreslovanému přes gldrawelements() toto umožňuje použít stejnou topologii pro různou geometrii všechny gldrawelements() varianty mají i verzi pro offset gldrawelementsbasevertex() gldrawrangeelementsbasevertex() gldrawelementsinstancedbasevertex() stejné parametry, pouze je zde navíc jeden parametr určující offset gldrawelementsbasevertex( GL_TRIANGLES, 0 GL_UNSIGNED_INT, BUFFER_OFFSET(offset), 15 ); Jan Horáček Geometry & Tesselation 10 / 42
Nepřímé vykreslování Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva parametry pro volání gldrawarraysinstanced() se dají uložit do GL_DRAW_INDIRECT_BUFFER data musí mít pevnou strukturu struct DrawArraysIndirectCommand { GLuint count; GLuint primcount; GLuint first; GLuint reservedmustbezero; }; // volání gldrawarraysindirect( primtype, BUFFER_OFFSET(offset) ); toto je připraveno pro budoucí způsoby vykreslování například dynamicky vytvářená geometrie Jan Horáček Geometry & Tesselation 11 / 42
Nepřímé vykreslování Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva podobně existuje i verze pro indexované vykreslování gldrawelementsindirect() struktura pro gldrawelementsindirect() struct DrawElementsIndirectCommand { GLuint count; GLuint primcount; GLuint firstindex; GLint basevertex; GLuint reservedmustbezero; }; Jan Horáček Geometry & Tesselation 12 / 42
Geometrická primitiva I Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva v 0 v 0 v 0 v 0 v 1 v 1 v 1 v 1 v 2 v 3 v 2 v 3 v 2 v 3 v 2 v 3 v 4 v 5 v 4 v 5 v 4 v 5 v 5 v 4 GL POINTS GL LINES GL LINE STRIP GL LINE LOOP Jan Horáček Geometry & Tesselation 13 / 42
Geometrická primitiva II Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva v 0 v 0 v 1 v 1 v 1 v 2 v 2 v 3 v 2 v 3 v 0 v 3 v 4 v 5 GL TRIANGLES v 4 v 5 GL TRIANGLE STRIP v 5 v 4 GL TRIANGLE FAN Jan Horáček Geometry & Tesselation 14 / 42
Geometrická primitiva III Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva v 6 v 5 v 6 v 5 v 7 v 4 v 7 v 4 v 0 v 1 v 2 v 3 v 0 v 1 v 2 v 3 GL LINES ADJACENCY GL LINE STRIP ADJACENCY Jan Horáček Geometry & Tesselation 15 / 42
Geometrická primitiva IV Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva v 5 v 0 v 5 v 9 v 1 v 2 v 6 v 10 v 4 v 1 v 3 v 2 GL TRIANGLES ADJACENCY v v v 4 0 v 11 8 v 3 v 7 GL TRIANGLE STRIP ADJACENCY Jan Horáček Geometry & Tesselation 16 / 42
Geometrická primitiva V Propojení Vykreslování Instancované a nepřímé vykreslování Geometrická primitiva?gl PATCHES Jan Horáček Geometry & Tesselation 17 / 42
Obsah Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader 1 2 3 4 Jan Horáček Geometry & Tesselation 18 / 42
Detaily scény Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader teselace se dá považovat za další krok v přidávání detailů do scény historicky: 1 jednobarevné a gouraudově stínované polygony - holé objekty 2 textury - barevný detail 3 bumpmapping (ve všech formách od emboss-bumpmappingu až po normalmapping/procedurální generování normál) - detail pro stínování, obzvláště dynamická světla 4 parallax mapping - falešný geometrický detail 5 teselace - skutečný geometrický detail toto je ovšem pouze jedno z možných využití teselace Jan Horáček Geometry & Tesselation 19 / 42
Přehled Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader teselace se využívá ke generování geometrie pouze jeden typ primitiv - patches do gldraw*() se uvede konstanta GL_PATCHES 3 fáze: 1 konfigurovatelná, 2 programovatelné pomocí shaderů tessellation control shader zpracovává sadu vstupních vertexových atributů generuje výstupní patchové atributy definuje teselační parametry tessellation evaluation shader zpracovává výstupní patchové atributy počítá finální vertexy generovaných primitiv Jan Horáček Geometry & Tesselation 20 / 42
OpenGL pipeline Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader Vertex data Vertex Shader Tesselation Control Shader Tesselation Evaluation Shader Geometry Shader Primitive Setup and Rasterization Fragment Shader Blending Pixel Data Texture Store Jan Horáček Geometry & Tesselation 21 / 42
Tok dat v teselační části pipeline Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader layout(vertices = n) out; gl_in[] Tesselation Control Shader gl_out[] gl_in[] Tesselation Evaluation Shader layout(prim, wind, spc) in; Vertex data Vertex Shader gl_tesslevelnner[] gl_tesslevelouter[] Tesselation Primitive Generator Jan Horáček Geometry & Tesselation 22 / 42
Tok dat v teselační části pipeline Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader teselační shadery pracují na sadách vrcholů vstupní i výstupní data jsou v poĺıch proměnná gl_in[] obsahuje vstupní data pro oba shadery délka pole = gl_in.length() proměnná gl_out[] má přepočítané informace o vrcholech obě jsou pole struktur in gl_pervertex { vec4 gl_position; float gl_pointsize; vec4 gl_clipdistance[]; } gl_in[]; Jan Horáček Geometry & Tesselation 23 / 42
Tesselation control shader Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader výstupní layout vertices specifikuje počet výstupních vertexů control shader spuštěn pro každý výstupní vertex vstupem i výstupem patch má přístup ke všem vstupním atributům smí zapisovat jen do svého výstupu podle gl_invocationid základní úkol je připravit parametry pro teselaci a přepočítat patch Jan Horáček Geometry & Tesselation 24 / 42
Příklad tessellation control shaderu Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader tessellation control shader #version 400 core layout (vertices = 4) out; uniform float Inner; uniform float Outer; void main() { gl_tesslevelinner[0] = Inner; gl_tesslevelinner[1] = Inner; gl_tesslevelouter[0] = Outer; gl_tesslevelouter[1] = Outer; gl_tesslevelouter[2] = Outer; gl_tesslevelouter[3] = Outer; } gl_out[gl_invocationid].gl_position = gl_in[gl_invocationid].gl_position; Jan Horáček Geometry & Tesselation 25 / 42
Tessellation control bez shaderu Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader mnoho programů pouze přeposílá data v případě, že vstupní a výstupní patch mají stejný počet vertexů, může OpenGL tuto stage nahradit 1 specifikuj počet vertexů ve vstupní patch glpatchparameteri( GL_PATCH_VERTICES, NumVertices ); 2 specifikuj vnitřní a vnější teselační parametry GLfloat outer[4], inner[2]; glpatchparameterfv( GL_PATCH_DEFAULT_OUTER_LEVEL, outer ); glpatchparameterfv( GL_PATCH_DEFAULT_INNER_LEVEL, inner ); Jan Horáček Geometry & Tesselation 26 / 42
Generování primitiv Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader teselace vytváří geometrická primitiva rozdělením parametrického prostoru k dispozici jsou tři typy parametrizací Typ Parametrický prostor Teselační faktory quad triangle isolines jednotkový čtverec: (u, v) gl_tesslevelinner: 0... 1 u, v [0, 1] gl_tesslevelouter: 0... 3 barycentrické: (u, v, w) gl_tesslevelinner: 0 u, v, w [0, 1] gl_tesslevelouter: 0... 2 u + v + w = 1 čára: (u, v) u, v [0, 1] gl_tesslevelouter: 0... 1 u se na čáře mění, v je konstantní Jan Horáček Geometry & Tesselation 27 / 42
Příklad teselace čtyřúhelníku Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader gl_tesslevelouter[3] (1,1) parametry gl_tesslevelinner[0] = 3.0; gl_tesslevelinner[1] = 4.0; gl_tesslevelouter[0] = 3.0; gl_tesslevelouter[1] = 4.0; gl_tesslevelouter[2] = 2.0; gl_tesslevelouter[3] = 3.0; gl_tesslevelouter[0] gl_tesslevelinner[0] gl_tesslevelinner[1] gl_tesslevelouter[2] (using equal_spacing) (0,0) gl_tesslevelouter[1] Jan Horáček Geometry & Tesselation 28 / 42
Příklad teselace trojúhelníku Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader parametry gl_tesslevelinner[0] = 5.0; gl_tesslevelouter[0] = 3.0; gl_tesslevelouter[1] = 4.0; gl_tesslevelouter[2] = 2.0; (using equal_spacing) gl_tesslevelouter[0] gl_tesslevelinner[0] gl_tesslevelouter[2] gl_tesslevelouter[1] Jan Horáček Geometry & Tesselation 29 / 42
Příklad teselace čar Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader (1,1) parametry gl_tesslevelouter[0] = 7.0; gl_tesslevelouter[1] = 4.0; (using equal_spacing) gl_tesslevelouter[0] (0,0) gl_tesslevelouter[1] Jan Horáček Geometry & Tesselation 30 / 42
Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader Příklad tessellation evaluation shaderu tessellation evaluation shader #version 400 core layout (quads, equal_spacing, ccw) in; uniform mat4 MV, P; float B( int i, float u) { const vec4 bc = vec4( 1, 3, 3, 1 ); return bc[i] * pow( u, i ) * pow( 1.0 - u, 3 - i ); } void main() { float u = gl_tesscoord.x, v = gl_tesscoord.y; } vec4 pos = vec4( 0.0 ); for( int j = 0; j < 4; j++ ) for( int i = 0; i < 4; i++ ) pos += B( i, u ) * B( j, v ) * gl_in[4*j+i].gl_position; gl_position = P * MV * pos; Jan Horáček Geometry & Tesselation 31 / 42
Kontrolování pozic teselace Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader teselační faktory jsou čísla s plovoucí řád. čárkou různé módy kontrolují, jak se bude strana rozdělovat každá hrana se může rozdělit na max. GL_MAX_TESS_GEN_LEVELS, aktuálně to je 64 Mód teselace Interval hodnot equal_spacing [1, max] fractional_even_spacing [2, max] fractional_odd_spacing [1, max-1] equal_spacing akceptuje celá čísla (zaokrouhluje nahoru), vytvoří n stejných intervalů fractional_... teselace zaokrouhĺı na nejbližší vyšší sudé/liché číslo, (n-2) intervalů je stejných a 2 většinou menší intervaly jsou závislé na desetinné části hodnoty Jan Horáček Geometry & Tesselation 32 / 42
Primitive winding a Point mode Úvod Tok dat Tesselation control shader Parametrizace Tesselation evaluation shader vytvořená primitiva mají vrcholy implicitně proti směru hodinových ručiček (ccw) použijte cw pro pořadí po směru hodinových ručiček místo polygonů (trojůhelníků) se dají generovat body, stačí nastavit point_mode v direktivě layout příklad nastavení layoutu v evaluation shaderu layout( triangles, cw, fractional_even_spacing, point_mode ) in; Jan Horáček Geometry & Tesselation 33 / 42
Obsah Přehled Příklad Geometry vs. Tessellation 1 2 3 4 Jan Horáček Geometry & Tesselation 34 / 42
Přehled Přehled Příklad Geometry vs. Tessellation poslední volitelná shader stage před rasterizerem svým způsobem podobné teselační části generování nové geometrie dosahuje podobných výsledků za pomocí jiných principů programátor specifikuje počet a typ vygenerovaných primitiv Jan Horáček Geometry & Tesselation 35 / 42
Vstup Přehled Příklad Geometry vs. Tessellation vstupem assembled primitives (tedy ne strips nebo fan) points... 1 lines... 2 lines_adjacency... 4 triangles... 3 triangles_adjacency... 6 má veškerou informaci o celém primitivu, nejen o 1 vrcholu nová primitiva se sousedností (adjacency) dodávají informaci o bezprostředním okoĺı Vestavěné proměnné in gl_pervertex { vec4 gl_position; float gl_pointsize; float gl_clipdistance[]; } gl_in[]; in int gl_primitiveidin; // pouze v OpenGL 4.0+ in int gl_invocationid; Jan Horáček Geometry & Tesselation 36 / 42
Výstup Přehled Příklad Geometry vs. Tessellation možná výstupní primitiva: points line_strip triangle_strip typy vstupního a výstupního primitiva jsou nezávislé vstup je po vykonání shaderu zapomenut výstupem 0 nebo více primitiv např. dva triangle_strips, každý ze 3 trojůhelníků pozn.:vzhledem k původní myšlence geometry shaderů nemusí být implementace nutně optimalizovaná pro masivní tvorbu geometrie na to je teselační část pipeline Jan Horáček Geometry & Tesselation 37 / 42
Výstupní proměnné Přehled Příklad Geometry vs. Tessellation Vestavěné proměnné vec4 gl_position; float gl_pointsize; float gl_clipdistance[]; out int gl_primitiveid; out int gl_layer; // pouze v OpenGL 4.0+ out int gl_viewportindex; Jan Horáček Geometry & Tesselation 38 / 42
Příklad geometry shaderu Přehled Příklad Geometry vs. Tessellation geometry shader #version 400 core layout (triangles, invocations = 1) in; layout (triangle_strip, max_vertices = 3) out; uniform float scale; void main() { vec4 v[3], center = vec4(0); for( int i = 0; i < 3; i++ ) { v[i] = gl_in[i].gl_position; center += v[i]; } center /= 3; for( int i = 0; i < 3; i++ ) { gl_position = mix( v[i], center, scale ); EmitVertex(); } EndPrimitive(); } Jan Horáček Geometry & Tesselation 39 / 42
Geometry vs. Tessellation Přehled Příklad Geometry vs. Tessellation Problém Geometry Tessellation generování primitiv topologie zdrojová primitiva praskliny mezi primitivy explicitní kontrola: specifikuje se pozice i propojení velmi lokalizovaná: je vidět jen nejbližší okoĺı s limitovanou konektivitou limitovaná sada: v podstatě jen základní primitiva, body, čáry, trojůhelníky problematické: je třeba dávat velký pozor na umístění vrcholů parametrická kontrola: teselační parametry určují počet vygenerovaných primitiv implicitně propojené: všechna primitiva jsou propojená, upravuje se jen umístění vrcholu jakákoliv patch: OpenGL vidí jen seznam vrcholů, vztahy se definují explicitně jednodušší: spoj je vodotěsný, pokud jsou teselační parametry stejné, praskání limitováno jen na výpočetní přesnost Jan Horáček Geometry & Tesselation 40 / 42
Obsah 1 2 3 4 Jan Horáček Geometry & Tesselation 41 / 42
OpenGL Architecture Review Board: OpenGL Programming Guide: The Official Guide to Learning OpenGL, Addison-Wesley, nejnovější vydání (aktuálně 8. vydání pro OpenGL 4.1) Randi J. Rost, Bill Licea-Kane: OpenGL Shading Language, 3 rd Edition, Addison-Wesley The Khronos Group: The OpenGL Graphics System: A Specification (Core/Compatibility profile), http://www.opengl.org/registry/ Christophe Riccino: OpenGL reviews, http://www.g-truc.net/post-opengl-review.html Wikipedia: http://en.wikipedia.org/wiki/opengl OpenGL tutorials: http://nehe.gamedev.net Jan Horáček Geometry & Tesselation 42 / 42